How to get a tool button showing up a label (Linux)

Just starting out? Need help? Post your questions and find answers here.
User avatar
Shardik
Addict
Addict
Posts: 2058
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: How to get a tool button showing up a label (Linux)

Post by Shardik »

uwekel wrote:It seems that i have missed something. Can anyone help?
Your premises are simply wrong! You expected to receive a GtkToolButton from ToolBarImageButton() although PB's help doesn't state any return value for this function! And the error message
assertion 'GTK_IS_TOOL_BUTTON(button)' failed
should already have given you the hint that ToolBarImageButton() doesn't return a GtkToolButton.

In these cases it is always helpful to analyse the widget structures PB is using. The following code (which is a slightly modified version of my Widget Explorer already posted here) demonstrates that although PB uses a GtkToolbar, it doesn't use GtkToolItems nor GtkToolButtons but a standard GtkButton with a GtkImage or a GtkLabel:

Code: Select all

GtkWindow
|
-- GtkVBox
    |
    -- GtkToolbar
        |
        -- GtkButton
            |
            -- GtkVBox
                |
                -- GtkImage
                |
                -- GtkLabel

Code: Select all

EnableExplicit

ImportC ""
  g_type_check_instance_is_a(*Instance.GTypeInstance, *Type.GTypeClass)
EndImport

Define SubnodeLevel.I

NewList FallbackSubnodeLevel.I()

Procedure.I GetChildren(*Widget.GtkWidget)
  Shared FallbackSubnodeLevel.I()
  Shared SubnodeLevel.I

  Protected *Child.GtkWidget
  Protected ChildrenCount.I
  Protected *ChildrenList.GList
  Protected i.I
  Protected *WidgetName
 
  If g_type_check_instance_is_a(*Widget\object\parent_instance\g_type_instance,
    gtk_container_get_type_()) = #False
    If ListSize(FallbackSubnodeLevel()) > 0
      LastElement(FallbackSubnodeLevel())
      SubnodeLevel = FallbackSubnodeLevel()
      DeleteElement(FallbackSubnodeLevel())
    EndIf
  Else
    *ChildrenList = gtk_container_get_children_(*Widget)
    ChildrenCount = g_list_length_(*ChildrenList)
   
    If ChildrenCount > 0
      For i = 0 To ChildrenCount - 1
        *Child = g_list_nth_data_(*ChildrenList, i)
        *WidgetName = gtk_widget_get_name_(*Child)
        AddGadgetItem(0, -1, PeekS(*WidgetName, -1, #PB_UTF8), 0, SubnodeLevel)
        LastElement(FallbackSubnodeLevel())
        AddElement(FallbackSubnodeLevel())
        FallbackSubnodeLevel() = SubnodeLevel
        SubnodeLevel + 1
        GetChildren(*Child)

        If i = ChildrenCount - 1
          If ListSize(FallbackSubnodeLevel()) > 0
            LastElement(FallbackSubnodeLevel())
            SubnodeLevel = FallbackSubnodeLevel()
            DeleteElement(FallbackSubnodeLevel())
          EndIf
        EndIf
      Next i
    EndIf
  EndIf
EndProcedure

Procedure ExamineWindows()
  Shared FallbackSubnodeLevel.I()
  Shared SubnodeLevel.I

  Protected *Child.GtkWidget
  Protected i.I

  Protected *WidgetName
  Protected WindowCount.I
  Protected *Window.GtkWindow
  Protected *WindowList.GList

  ClearGadgetItems(0)

  *WindowList = gtk_window_list_toplevels_()
  WindowCount = g_list_length_(*WindowList)
 
  If WindowCount > 0
    For i = 0 To WindowCount - 1
      *Window = g_list_nth_data_(*WindowList, i)
      AddGadgetItem(0, -1, "GtkWindow", 0, 0)
      ClearList(FallbackSubnodeLevel())
      SubnodeLevel = 1
      GetChildren(*Window)
    Next i
  EndIf

  gtk_tree_view_expand_all_(GadgetID(0))
EndProcedure

OpenWindow(0, 100, 100, 460, 300, "Widget Explorer")
TreeGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 60)

CreateToolBar(0, WindowID(0))

; ----- Create tool button image
CreateImage(0, 16, 16)
StartDrawing(ImageOutput(0))
  Box(1, 1, 14, 14, $FF)
StopDrawing()
 
; ----- Create a standard tool button with an image
ToolBarImageButton(0, ImageID(0))

ExamineWindows()

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Update 1: I have fixed a bug in the procedure GetChildren(). The previous example code worked correctly but didn't work correctly anymore when adding 2 or more further ToolBarButtons. I furthermore removed some unneccessary declarations.

Update 2: I have removed the display of a compiler error when compiling in Unicode mode and modified the example to work in ASCII and Unicode mode.

I have modified your example to display your toolbar button with a label:

Code: Select all

ImportC ""
  gtk_tool_button_new(*Icon.GtkWidget, Label.P-UTF8)
EndImport

If OpenWindow(0, 0, 0, 300, 250, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  *tb = CreateToolBar(0, WindowID(0))
 
  ;create tool button image
  *im = CreateImage(0, 16, 16)
  StartDrawing(ImageOutput(0))
  Box(1, 1, 14, 14, $FF)
  StopDrawing()
 
  ;create an API tool button with an image and a label
  ImageWidget = gtk_image_new_from_pixbuf_(*im)
  *bt = gtk_tool_button_new(ImageWidget, "Hello")
  gtk_toolbar_set_style_(*tb, #GTK_TOOLBAR_BOTH)
  gtk_toolbar_insert_(*tb, *bt, -1)
  gtk_widget_show_all_(WindowID(0))

  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Last edited by Shardik on Sat Mar 09, 2019 6:27 pm, edited 2 times in total.
uwekel
Enthusiast
Enthusiast
Posts: 740
Joined: Sat Dec 03, 2011 5:54 pm
Location: Oldenburg (Germany)

Re: How to get a tool button showing up a label (Linux)

Post by uwekel »

Hello Shardik,

thank you very much for your help!
should already have given you the hint that ToolBarImageButton() doesn't return a GtkToolButton.
Unfortunately i disabled the compiler warnings so i did not see that hint :-(

Your example with the button label is good, but i want it to fire a standard menu event so i have to use a ToolbarImageButton().

Anyhow, with your help, i could get one step further. Now i can see the label. Look here:

Code: Select all

If OpenWindow(0, 0, 0, 300, 250, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

  ;create tool bar
  *toolbar = CreateToolBar(0, WindowID(0))
  gtk_toolbar_set_style_(*toolbar, #GTK_TOOLBAR_BOTH_HORIZ)
  
  ;create tool button image
  *im = CreateImage(0, 16, 16)
  StartDrawing(ImageOutput(0))
  Box(1, 1, 14, 14, $FF)
  StopDrawing()
  
  ;create a standard tool button with an image
  *button = ToolBarImageButton(0, *im)
  
  ;get vbox inside button
  *children = gtk_container_get_children_(*button)
  *vbox = g_list_nth_data_(*children, 0)

  ;set spacing between image and label 
  gtk_box_set_spacing_(*vbox, 4)
  
  ;image and label
  *children = gtk_container_get_children_(*vbox)
  *image = g_list_nth_data_(*children, 0)
  *label = g_list_nth_data_(*children, 1)

  ;set the tool buttons label  
  gtk_label_set_label_(*label, "Cool")
  
  *button2 = ToolBarImageButton(1, *im)
  
  Repeat
    Select WaitWindowEvent()
    Case #PB_Event_Menu
      Debug EventMenu()
    Case #PB_Event_CloseWindow
      Break
    EndSelect
  ForEver
  
EndIf
But the second button has the same width as the first one. Do you now how to make the second button smaller (as usual)?

Best regards
Uwe
PB 5.70 LTS (x64) - Debian Testing, Gnome 3.30.2
User avatar
Shardik
Addict
Addict
Posts: 2058
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: How to get a tool button showing up a label (Linux)

Post by Shardik »

uwekel wrote:But the second button has the same width as the first one. Do you now how to make the second button smaller (as usual)?
I currently don't have found a simple solution so far because the toolbar doesn't contain a HBox or VBox but only one or several GtkButtons. So when changing the properties of the parent VBox of the toolbar, all GtkButtons are effected in the same way. (By the way when integrating your code into my Widget Explorer code you will see that PB changes the VBox of a single GtkButton to HBoxes if using multiple GtkButtons... :wink:)

Therefore I propose to go the way of using solely GtkToolButtons. Take a look into my new example which uses the procedure AddToolBarImageButton() to define new buttons with a callback for each button and a PostEvent() in the callback so that you receive the button numbers in the main event loop much similar as in your previous example:

Code: Select all

EnableExplicit

ImportC ""
  g_signal_connect_data(*Instance, SignalName.P-UTF8, Callback.I, *UserData,
    ClosureNotify.I, ConnectFlags.I)
EndImport

Define ToolBar.I

NewMap ToolBarButton.I()

ProcedureC ToolBarButtonCallback(ToolBarButtonID.I, UserData.I)
  Shared ToolBarButton.I()

  PostEvent(#PB_Event_Menu, 0, 0, #PB_EventType_LeftClick,
    ToolBarButton(Str(ToolBarButtonID)) + 1)
EndProcedure

Procedure AddToolBarImageButton(ToolBar.I, IconName.S)
  Shared ToolBarButton.I()
  Static ToolBarButtonIndex.I
  Protected ToolBarButtonID.I = gtk_tool_button_new_from_stock_(IconName)

  ToolBarButton(Str(ToolBarButtonID)) = ToolBarButtonIndex
  ToolBarButtonIndex + 1
  gtk_toolbar_insert_(ToolBar, ToolBarButtonID, -1)
  g_signal_connect_data(ToolBarButtonID, "clicked", @ToolBarButtonCallback(),
    0, 0, 0)
EndProcedure

Procedure.S ConvertToUTF8(String.S)
  Protected UTF8String.S

  UTF8String = Space(StringByteLength(String, #PB_UTF8))
  PokeS(@UTF8String, String, -1, #PB_UTF8)

  ProcedureReturn UTF8String
EndProcedure

If OpenWindow(0, 270, 100, 300, 250, "API toolbar buttons")
  ToolBar = CreateToolBar(0, WindowID(0))
  gtk_toolbar_set_style_(ToolBar, #GTK_TOOLBAR_BOTH)

  AddToolBarImageButton(ToolBar, ConvertToUTF8(#GTK_STOCK_ADD))
  AddToolBarImageButton(ToolBar, ConvertToUTF8(#GTK_STOCK_COPY))
  AddToolBarImageButton(ToolBar, ConvertToUTF8(#GTK_STOCK_CANCEL))
  gtk_widget_show_all_(WindowID(0))

  Repeat
    Select WaitWindowEvent()
    Case #PB_Event_Menu
      If EventType() = #PB_EventType_LeftClick
        If EventData()
          Debug EventData() - 1
        EndIf
      EndIf
    Case #PB_Event_CloseWindow
      Break
    EndSelect
  ForEver
EndIf
Update: I have modified the above code to work in both ASCII and Unicode mode.
Post Reply