4.3. Packing Demonstration Program

Here is the code used to create the above images. It's commented fairly heavily so I hope you won't have any problems following it. Run it yourself and play with it.

   1    #!/usr/bin/env gst                                                 
   2                                                                       
   3    " example packbox.st"                                              
   4                                                                       
   5    Eval [                                                             
   6        PackageLoader fileInPackage: 'GTK'.                            
   7    ]                                                                  
   8                                                                       
   9    Object subclass: PackageBox [                                      
  10            | box1 box2 button label quitbox separator window |        
  11                                                                       
  12            " Helper function that makes a new hbox filled with button-labels. Arguments
  13              for the variables we're interested are passed in to this function.  We do 
  14              not show the box, but do show everything inside. "                        
  15            makeBox: aHomogeneousBool spacing: aSpacingInt expand: anExpandBool fill: aFillBool padding: aPaddingInt [
  16                    | box padstr |                                                                                    
  17                                                                                                                      
  18                    " Create a new hbox with the appropriate homogeneous                                              
  19                      and spacing settings "                                                                          
  20                    box := GTK.GtkHBox new: aHomogeneousBool spacing: aSpacingInt.                                    
  21                                                                                                                      
  22                    " Create a series of buttons with the appropriate settings "                                      
  23                    button := GTK.GtkButton newWithLabel: 'box.pack'.                                                 
  24                    box packStart: button expand: anExpandBool fill: aFillBool padding: aPaddingInt.                  
  25                    button show.                                                                                      
  26                                                                                                                      
  27                    button := GTK.GtkButton newWithLabel: '(button,'.                                                 
  28                    box packStart: button expand: anExpandBool fill: aFillBool padding: aPaddingInt.                  
  29                    button show.                                                                                      
  30                                                                                                                      
  31                    " Create a button with the label depending on the value of                                        
  32                      expand. "                                                                                       
  33                    anExpandBool                                                                                      
  34                            ifTrue: [ button := GTK.GtkButton newWithLabel: 'true,' ]                                 
  35                            ifFalse: [ button := GTK.GtkButton newWithLabel: 'false,' ].                              
  36                                                                                                                      
  37                    box packStart: button expand: anExpandBool fill: aFillBool padding: aPaddingInt.                  
  38                    button show.                                                                                      
  39                                                                                                                      
  40                    " This is the same as the button creation for 'expand'                                            
  41                      above, but uses the shorthand form. "                                                           
  42                    button := GTK.GtkButton newWithLabel: (aFillBool ifTrue: [ 'true,' ] ifFalse: [ 'false,' ]).      
  43                    box packStart: button expand: anExpandBool fill: aFillBool padding: aPaddingInt.                  
  44                    button show.                                                                                      
  45                                                                                                                      
  46                    padstr := aPaddingInt asString, ')'.                                                              
  47                                                                                                                      
  48                    button := GTK.GtkButton newWithLabel: padstr.                                                     
  49                    box packStart: button expand: anExpandBool fill: aFillBool padding: aPaddingInt.                  
  50                    button show.                                                                                      
  51                    ^ box                                                                                             
  52            ]                                                                                                         
  53                                                                                                                      
  54        delete: aWidget event: aGdkEvent [                                                                            
  55            GTK.Gtk mainQuit.                                                                                         
  56            ^ false                                                                                                   
  57            ]                                                                                                         
  58                                                                                                                      
  59            box1 [                                                                                                    
  60                    | label separator |                                                                               
  61                                                                                                                      
  62                    " create a new label. "                                                                           
  63                    label := GTK.GtkLabel new: 'HBox(false, 0)'.                                                      
  64                                                                                                                      
  65                    " Align the label to the left side.  We'll discuss this method                                    
  66                      and others in the section on Widget Attributes. "                                               
  67                    label setAlignment: 0 yalign: 0.                                                                  
  68                                                                                                                      
  69                    " Pack the label into the vertical box (vbox box1).  Remember that                                
  70                      widgets added to a vbox will be packed one on top of the other in                               
  71                      order. "                                                                                        
  72                    box1 packStart: label expand: false fill: false padding: 0.                                       
  73                                                                                                                      
  74                    " Show the label "                                                                                
  75                    label show.                                                                                       
  76                                                                                                                      
  77                    " Call our make box function - homogeneous = false, spacing = 0,                                  
  78                      expand = false, fill = false, padding = 0 "                                                     
  79                    box2 := self makeBox: false spacing: 0 expand: false fill: false padding: 0.                      
  80                    box1 packStart: box2 expand: false fill: false padding: 0.                                        
  81                    box2 show.                                                                                        
  82                                                                                                                      
  83                    " Call our make box function - homogeneous = false, spacing = 0,                                  
  84                      expand = true, fill = false, padding = 0 "                                                      
  85                    box2 := self makeBox: false spacing: 0 expand: true fill: false padding: 0.                       
  86                    box1 packStart: box2 expand: false fill: false padding: 0.                                        
  87                    box2 show.                                                                                        
  88                                                                                                                      
  89                    " Args are: homogeneous, spacing, expand, fill, padding "                                         
  90                    box2 := self makeBox: false spacing: 0 expand: true fill: true padding: 0.                        
  91                    box1 packStart: box2 expand: false fill: false padding: 0.                                        
  92                    box2 show.                                                                                        
  93                                                                                                                      
  94                    " Creates a separator, we'll learn more about these later,                                        
  95                      but they are quite simple. "                                                                    
  96                    separator := GTK.GtkHSeparator new.                                                               
  97                                                                                                                      
  98                    " Pack the separator into the vbox. Remember each of these                                        
  99                      widgets is being packed into a vbox, so they'll be stacked                                      
 100                      vertically. "                                                                                   
 101                    box1 packStart: separator expand:false fill: true padding: 5.                                     
 102                    separator show.                                                                                   
 103                                                                                                                      
 104                    " Create another new label, and show it. "                                                        
 105                    label := GTK.GtkLabel new: 'HBox(true, 0)'.                                                       
 106                    label setAlignment: 0 yalign: 0.                                                                  
 107                    box1 packStart: label expand: false fill: false padding: 0.                                       
 108                    label show.                                                                                       
 109                                                                                                                      
 110                    " Args are: homogeneous, spacing, expand, fill, padding "                                         
 111                    box2 := self makeBox: true spacing: 0 expand: true fill: false padding: 0.                        
 112                    box1 packStart: box2 expand: false fill: false padding: 0.                                        
 113                    box2 show.                                                                                        
 114                                                                                                                      
 115                    " Args are: homogeneous, spacing, expand, fill, padding "                                         
 116                    box2 := self makeBox: true spacing: 0 expand: true fill: true padding: 0.                         
 117                    box1 packStart: box2 expand: false fill: false padding: 0.                                        
 118                    box2 show.                                                                                        
 119                                                                                                                      
 120                    " Another new separator. "                                                                        
 121                    separator := GTK.GtkHSeparator new.                                                               
 122                    " The last 3 arguments to pack_start are:                                                         
 123                      expand, fill, padding. "                                                                        
 124                    box1 packStart: separator expand: false fill: true padding: 5.                                    
 125                    separator show                                                                                    
 126            ]                                                                                                         
 127                                                                                                                      
 128            box2 [                                                                                                    
 129                    " Create a new label, remember box1 is a vbox as created                                          
 130                      near the beginning of show: "                                                                   
 131                    label := GTK.GtkLabel new: 'HBox(false, 10)'.                                                     
 132                    label setAlignment: 0 yalign: 0.                                                                  
 133                    box1 packStart: label expand: false fill: false padding: 0.                                       
 134                    label show.                                                                                       
 135                                                                                                                      
 136                    " Args are: homogeneous, spacing, expand, fill, padding "                                         
 137                    box2 := self makeBox: false spacing: 10 expand: true fill: false padding: 0.                      
 138                    box1 packStart: box2 expand: false fill: false padding: 0.                                        
 139                    box2 show.                                                                                        
 140                                                                                                                      
 141                    " Args are: homogeneous, spacing, expand, fill, padding "                                         
 142                    box2 := self makeBox: false spacing: 10 expand: true fill: true padding: 0.                       
 143                    box1 packStart: box2 expand: false fill: false padding: 0.                                        
 144                    box2 show.                                                                                        
 145                                                                                                                      
 146                    separator := GTK.GtkHSeparator new.                                                               
 147                    " The last 3 arguments to pack_start are:                                                         
 148                      expand, fill, padding. "                                                                        
 149                    box1 packStart: separator expand: false fill: true padding: 5.                                    
 150                    separator show.                                                                                   
 151                                                                                                                      
 152                    label := GTK.GtkLabel new: 'HBox(false, 0)'.                                                      
 153                    label setAlignment: 0 yalign: 0.                                                                  
 154                    box1 packStart: label expand: false fill: false padding: 0.                                       
 155                    label show.                                                                                       
 156                                                                                                                      
 157                    " Args are: homogeneous, spacing, expand, fill, padding "                                         
 158                    box2 := self makeBox: false spacing: 0 expand: true fill: false padding: 10.                      
 159                    box1 packStart: box2 expand: false fill: false padding: 0.                                        
 160                    box2 show.                                                                                        
 161                                                                                                                      
 162                    " Args are: homogeneous, spacing, expand, fill, padding "                                         
 163                    box2 := self makeBox: false spacing: 0 expand: true fill: true padding: 10.                       
 164                    box1 packStart: box2 expand: false fill: false padding: 0.                                        
 165                    box2 show.                                                                                        
 166                                                                                                                      
 167                    separator := GTK.GtkHSeparator new.                                                               
 168                    " The last 3 arguments to pack_start are:                                                         
 169                      expand, fill, padding. "                                                                        
 170                    box1 packStart: separator expand: false fill: true padding: 5.                                    
 171                    separator show.                                                                                   
 172            ]                                                                                                         
 173                                                                                                                      
 174            box3 [                                                                                                    
 175                    " This demonstrates the ability to use packEnd to                                                 
 176                      right justify widgets. First, we create a new box as before. "                                  
 177                    box2 := self makeBox: false spacing: 0 expand: false fill: false padding: 0.                      
 178                                                                                                                      
 179                    " Create the label that will be put at the end. "                                                 
 180                    label := GTK.GtkLabel new: 'end'.                                                                 
 181                    " Pack it using packEnd, so it is put on the right                                                
 182                      side of the hbox created in the makeBox: call. "                                                
 183                    box2 packEnd: label expand: false fill: false padding: 0.                                         
 184                    " Show the label. "                                                                               
 185                    label show.                                                                                       
 186                                                                                                                      
 187                    " Pack box2 into box1 "                                                                           
 188                    box1 packStart: box2 expand: false fill: false padding: 0.                                        
 189                    box2 show.                                                                                        
 190                                                                                                                      
 191                    " A separator for the bottom. "                                                                   
 192                    separator := GTK.GtkHSeparator new.                                                               
 193                                                                                                                      
 194                    " This explicitly sets the separator to 400 pixels wide by 5                                      
 195                      pixels high. This is so the hbox we created will also be 400                                    
 196                      pixels wide, and the 'end' label will be separated from the                                     
 197                      other labels in the hbox. Otherwise, all the widgets in the                                     
 198                      hbox would be packed as close together as possible. "                                           
 199                    separator setSizeRequest: 400 height: 5.                                                          
 200                    " pack the separator into the vbox (box1) created near the start                                  
 201                      of show: "                                                                                      
 202                    box1 packStart: separator expand: false fill: true padding: 5.                                    
 203                    separator show.                                                                                   
 204            ]                                                                                                         
 205                                                                                                                      
 206            show: aSymbol [                                                                                           
 207                    " Create our window "                                                                             
 208                    window := GTK.GtkWindow new:GTK.Gtk gtkWindowToplevel.                                            
 209                                                                                                                      
 210                    " You should always remember to connect the delete_event signal                                   
 211                      to the main window. This is very important for proper intuitive                                 
 212                      behavior "
 213                    window connectSignal: 'delete_event' to: self selector: #delete:event: userData: nil.
 214                    window setBorderWidth: 10.
 215
 216                    " We create a vertical box (vbox) to pack the horizontal boxes into.
 217                      This allows us to stack the horizontal boxes filled with buttons one
 218                      on top of the other in this vbox. "
 219                    box1 := GTK.GtkVBox new: false spacing: 0.
 220
 221                    " which example to show. These correspond to the pictures above. "
 222                    self perform: aSymbol.
 223
 224                    " Create another new hbox.. remember we can use as many as we need! "
 225                    quitbox := GTK.GtkHBox new: false spacing: 0.
 226
 227                    " Our quit button. "
 228                    button := GTK.GtkButton newWithLabel: 'Quit'.
 229
 230                    " Setup the signal to terminate the program when the button is clicked "
 231                    button connectSignal: 'clicked' to: self selector: #delete:event:.
 232
 233                    " Pack the button into the quitbox.
 234                      The last 3 arguments to pack_start are:
 235                      expand, fill, padding. "
 236                    quitbox packStart: button expand: true fill: false padding: 0.
 237                    " pack the quitbox into the vbox (box1) "
 238                    box1 packStart: quitbox expand: false fill: false padding: 0.
 239
 240                    " Pack the vbox (box1) which now contains all our widgets, into the
 241                      main window. "
 242                    window add: box1.
 243
 244                    " And show everything left "
 245                    button show.
 246                    quitbox show.
 247
 248                    box1 show.
 249                    " Showing the window last so everything pops up at once. "
 250                    window show.
 251      ]
 252    ]
 253
 254    Eval [
 255            package := PackageBox new.
 256            package show: Smalltalk arguments first asSymbol.
 257            GTK.Gtk main
 258    ]

A brief tour of the packbox.st code starts with lines 15-52 which define a helper function makeBox that creates a horizontal box and populates it with buttons according to the specified parameters. A reference to the horizontal box is returned.

Lines 9-251 define the PackBox class initialization method show that creates a window and a child vertical box that is populated with a different widget arrangement depending on the argument passed to it. If a box1 is passed, lines 59-126 define the method box1 creates a window displaying the five unique packing arrangements that are available when varying the homogeneous, expand and fill parameters. If a box2 is passed, lines 128-172 define the method box2 creates a window displaying the various combinations of fill with spacing and padding. Finally, if a 3 is passed, lines 174-204 define the method box1 creates a window displaying the use of the packStart method to left justify the buttons and packEnd method to right justify a label. Lines 225-238 create a horizontal box containing a button that is packed into the vertical box. The button "clicked" signal is connected to the Smalltalk delete:event: function to terminate the program.

Lines 255-257 check the command line arguments and exit the program using the ObjectMemory quit: 0 function if there isn't exactly one argument. Line 257 invokes the GTK.Gtk main function to start the GTK event processing loop.