Luie programmeurs: automatische naam voor button

Als je aan het programmeren bent en je snel wat knoppen in je vensters zet, is het belangrijk om die knoppen een relevante naam te geven.

Bv een nieuwe knop Button1 krijgt de naam buttonQuit of in mijn geval btQuit (ik kort de prefix voor het schermobjecttype af tot 2 of 4 lettertekens zoals bt, lsbx, cmbx, enz).

De knoppen hebben ook een functie naar de gebruiker, je moet ze dus ook een etiket geven voor de gebruiker, de Text property: Button1.Text of bij mij: btQuit.Text=”Quit”.

Zie je de luiheid al opkomen? In de nieuwere versies van Gambas (Gambas3) wordt de Button1.Name ook weergegeven op de knop als je zelf nog geen tekst erin zette; dit is bijzonder handig tijdens het programmeren.

Maar als die tekst eens ineens kan blijven staan als goede tekst? In mijn geval zou btQuit wel de opdruk “Quit” moeten krijgen, dus de twee letterjes prefix van het type moeten eraf. Right(Button1.Text, -2) als het ware.

Daar gaan we dus:

In een steeds in mijn projecten voorkomende schermfunctiesverzameling plant ik deze:

MForm

Public Sub doNameButtons(hMainObject As Object)
  '
  Dim hObject As Object
  Dim hButton As Button
  Dim iChildrenCount As Integer
  '
  Debug hMainObject.Name & " " & TypeOf(hMainObject)
  '
  Try iChildrenCount = hMainObject.Children.Count
  '
  If Not Error 
    '
    For Each hObject In hMainObject.Children
      '
      Try hButton = hObject
      '
      If Not Error
        If Left(hObject.Name, 2) = "bt" And hButton.Text = ""
          Debug "CHANGE TO " & Right(hObject.Name, -2)
          hButton.Text = Right(hObject.Name, -2)
        Else
          ' not named with naming convention of buttons, this is a way to let you exclude empty-text buttons from this auto-name 
          ' name not empty, so it stays as it is - and can be translated 
          Debug "NO CHANGE: " & hObject.Name
        Endif
      Else
        ' recursion
        Debug hObject.Name & " is no button; check for .children : "
        doNameButtons(hObject)
      Endif        
    Next
  Else
    Debug "Error hMainObject.Children.Count " & hMainObject.Name & " " & iChildrenCount
  Endif  
End
'

In mijn FMain (en alle andere schermen die ik snel in elkaar flikker) roep ik dat zo aan voor iedere container met buttons in (soms nog eens in een container – dus recursief):

FMain

Public Sub Form_Open()
'
  MForm.doNameButtons(HBox1)
' ...
End

Alle knoppen in de Form die al een opschrift hebben, houden die. De anderen krijgen één, afgeleid van de knopnaam.

Let op!
Dit is alleen handig tijdens het programmeren, als de knoppen nog van functie en naam veranderen enz.

Eens het project zo ver af is dat je het gaat vertalen zul je toch de Text properties van de knoppen moeten invullen, anders werkt het vertaalsysteem niet.

Check eerst of het een button is:

TypeOf(hObject) = TypeOf(hButton)

Dit is geen oplossing, omdat er niet zo’n fijn onderscheid wordt gemaakt tussen objecten in TypeOf; beiden zijn “16” (een constante voor gb.Object); ook een HBox of VBox behoort daartoe.

Ik vond geen andere methode dan het child object proberen toe te wijzen aan een button; bij fout is het geen button, anders wel.

Zelfs tussen buttons kan er een ander object staan zoals een leeg tekstveld om als “spacer” te gebruiken; tekst leeg maar expand=TRUE zodat het een knop aan de rechterkant naar rechts tot aan het einde van de container (bv HBox) duwt.

Hernoemen uitvoeren op button object met naam beginnend met “bt”, de anderen worden overgeslagen.

Recursie
Als het object geen button was, kan het altijd nog een container zijn die ook weer buttons bevat, dus wordt dat gecheckt en kan de hernoem-test opnieuw beginnen.
Daarom wordt de procedure zelf terug opgeroepen.

Ik vond ook geen mooie manier om te testen of het een container is, en als er geen children objecten zijn, crasht

For Each hObject In hMainObject.Children

Daarom test ik eerst of een Children.Count wel kan:

Try iChildrenCount += hMainObject.Children.Count

If Not Error

(het optellen heeft niet echt zin)

Upd 13092017: bug fix: crash bij ander object dan button en helemaal herwerkt.