Magic of GTKCellRenderer :)

In dieser Linux-Ecke dürfen nur Themen rund um Linux geschrieben werden.
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Magic of GTKCellRenderer :)

Beitrag von ccode_new »

Hallo GTK-Linux-Freaks!

Kann man (oder wie kann man) mit Hilfe eines GTKCellRenderes die Linien eines ListViews einfärben.
(Nicht nur den Texthintergrund (wie im Beispiel), sondern die ganze internen Label-Box).
Und wie kann man z.B diesen Callback vermeiden ?

Mit CSS scheint es nicht Möglich zu sein. (bzw. ich habe keine Ahnung!)

Dafür scheint die Magie des GTK-Cellrenderer nötig zu sein, oder ?

Hier ein kleines CellRenderer-Beispiel:

(Es erfühlt nicht annähernd meine Bedingung :mrgreen: )

Code: Alles auswählen

ImportC ""
  gtk_css_provider_load_from_data(*css_provider, data_.p-utf8, length, *error.GError)
  gtk_css_provider_new()
  gtk_style_context_add_provider(*context, *provider, priority)
  gtk_style_context_remove_provider(*context, *provider)
  gtk_widget_get_style_context(*widget.GtkWidget)
  g_object_set(*Object.GtkObject, property.p-utf8, value.i, term.i = 0)
  g_type_check_instance_is_a(*Instance.GTypeInstance, *Type.GTypeClass)
  gtk_cell_layout_get_cells(*cell_layout)
EndImport

ProcedureC ColumnRenderingCallback(*Column.GtkTreeViewColumn, *Renderer.GtkCellRenderer, *Model, *Iter.GtkTreeIter, *UserData)
  Protected CellText.S
  Protected CellTextUTF8.S
  Protected Row.I

  Row = Val(PeekS(gtk_tree_model_get_string_from_iter_(*Model, *Iter), -1, #PB_UTF8))

  CellText = GetGadgetItemText(0, Row, 0)
  CellTextUTF8 = Space(StringByteLength(CellText, #PB_UTF8))
  PokeS(@CellTextUTF8, CellText, -1, #PB_UTF8)
  g_object_set(*Renderer, "markup", @CellTextUTF8)
EndProcedure

If OpenWindow(0, 0, 0, 270, 140, "ListViewGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  ListViewGadget(0, 10, 10, 250, 120)
  For a = 1 To 12
    AddGadgetItem (0, -1, ~"<span bgcolor=\"#ffff00\"> Item </span> " + Str(a) + " of the Listview")
  Next
  
    
  Column = gtk_tree_view_get_column_(GadgetID(0), 0)
  RendererList = gtk_cell_layout_get_cells(Column)
  Renderer = g_list_nth_data_(RendererList, 1)
  
  For i = 0 To g_list_length_(RendererList) - 1
    Renderer = g_list_nth_data_(RendererList, i)
    
    If g_type_check_instance_is_a(Renderer, gtk_cell_renderer_text_get_type_())
      Break
    EndIf
  Next i
  
  g_list_free_(RendererList)
  
  If Renderer
    gtk_tree_view_column_set_cell_data_func_(Column, Renderer, @ColumnRenderingCallback(), 0, 0) ;Wie umgehe ich den Callback ?
  EndIf
  
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Magic of GTKCellRenderer :)

Beitrag von ccode_new »

Wie kann ich einzelne Reihen (row) auswählen ?

Bis jetzt funktioniert es mit der ganzen Spalte.

Code: Alles auswählen

ImportC ""
  gtk_css_provider_load_from_data(*css_provider, data_.p-utf8, length, *error.GError)
  gtk_css_provider_new()
  gtk_style_context_add_provider(*context, *provider, priority)
  gtk_style_context_remove_provider(*context, *provider)
  gtk_widget_get_style_context(*widget.GtkWidget)
  g_object_set(*Object.GtkObject, property.p-utf8, value.i, term.i = 0)
  g_type_check_instance_is_a(*Instance.GTypeInstance, *Type.GTypeClass)
  gtk_cell_layout_get_cells(*cell_layout)
EndImport

Procedure SetListLineColors(Gadget, col, row, fgcolor, bgcolor)
  Protected.i Column, RenderList, Renderer
  Protected.s color_str
  
  Column = gtk_tree_view_get_column_(GadgetID(Gadget), col)
  RendererList = gtk_cell_layout_get_cells(Column)
  
  For i = 0 To g_list_length_(RendererList) - 1
    Renderer = g_list_nth_data_(RendererList, i)
    
    If g_type_check_instance_is_a(Renderer, gtk_cell_renderer_text_get_type_())
      Break
    EndIf
  Next i
  
  g_list_free_(RendererList)
  
  If Renderer
    color_str =  "rgb("+Str(Red(bgcolor))+","+Str(Green(bgcolor))+","+Str(Blue(bgcolor))+")"
    g_object_set(Renderer, "cell-background", UTF8(color_str))
    color_str =  "rgb("+Str(Red(fgcolor))+","+Str(Green(fgcolor))+","+Str(Blue(fgcolor))+")"
    g_object_set(Renderer, "foreground", UTF8(color_str))
  EndIf
EndProcedure

If OpenWindow(0, 0, 0, 270, 140, "ListViewGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  ListViewGadget(0, 10, 10, 250, 120)
  For a = 1 To 12
    AddGadgetItem (0, -1, ~"Item " + Str(a) + " of the Listview")
  Next
  
  SetListLineColors(0, 0, 0, RGB(255,0,0), RGB(255,255,0))  

  
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Omi
Beiträge: 143
Registriert: 25.03.2013 09:59

Re: Magic of GTKCellRenderer :)

Beitrag von Omi »

Hallo ccode_new,

wenn Du das Callback nicht setzt, gilt die für die oberste Zeile gesetzt Eigenschaft für die ganze Spalte wenn ich mich recht entsinne. Du könntest Dir also den Rest sparen (falls ich nicht falsch liege).
Ein hingeschludertes, hardgecodetes Beispiel für alternierende Farben ...

Code: Alles auswählen

ImportC ""
  gtk_css_provider_load_from_data(*css_provider, data_.p-utf8, length, *error.GError)
  gtk_css_provider_new()
  gtk_style_context_add_provider(*context, *provider, priority)
  gtk_style_context_remove_provider(*context, *provider)
  gtk_widget_get_style_context(*widget.GtkWidget)
  g_object_set(*Object.GtkObject, property1.p-utf8, value1.p-utf8, term.i = 0)
;   g_object_set2(*Object.GtkObject, property1.p-utf8, value1.p-utf8, property2.p-utf8, value2.i, term.i = 0) As "g_object_set"
  g_type_check_instance_is_a(*Instance.GTypeInstance, *Type.GTypeClass)
  gtk_cell_layout_get_cells(*cell_layout)
EndImport

ProcedureC ColumnRenderingCallback(*Column.GtkTreeViewColumn, *Renderer.GtkCellRenderer, *Model, *Iter.GtkTreeIter, *UserData)
  Protected CellText.S
  Protected CellTextUTF8.S
  Protected Row.I

  Row = Val(PeekS(gtk_tree_model_get_string_from_iter_(*Model, *Iter), -1, #PB_UTF8))
  If Row % 2
  	CellText = GetGadgetItemText(0, Row, 0)
  	CellTextUTF8 = Space(StringByteLength(CellText, #PB_UTF8))
  	PokeS(@CellTextUTF8, CellText, -1, #PB_UTF8)
;   	g_object_set2(*Renderer, "cell-background", "yellow", "cell-background-set", 1)
  	g_object_set(*Renderer, "cell-background", "yellow")
  Else
  	g_object_set(*Renderer, "cell-background", "white")
  EndIf
EndProcedure

If OpenWindow(0, 0, 0, 270, 140, "ListViewGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
 
  ListViewGadget(0, 10, 10, 250, 120)
  For a = 1 To 12
    AddGadgetItem (0, -1, ~"<span bgcolor=\"#ffff00\"> Item </span> " + Str(a) + " of the Listview")
  Next
 
   
  Column = gtk_tree_view_get_column_(GadgetID(0), 0)
  RendererList = gtk_cell_layout_get_cells(Column)
 
  For i = 0 To g_list_length_(RendererList) - 1
    Renderer = g_list_nth_data_(RendererList, i)
   
    If g_type_check_instance_is_a(Renderer, gtk_cell_renderer_text_get_type_())
      gtk_tree_view_column_set_cell_data_func_(Column, Renderer, @ColumnRenderingCallback(), 0, 0) ;Wie umgehe ich den Callback ?
    EndIf
  Next i
 
  g_list_free_(RendererList)
 
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Gruß, Charly
PureBasic Linux-API-Library: http://www.chabba.de
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Magic of GTKCellRenderer :)

Beitrag von ccode_new »

Danke!

Zur Zeit scheinen hier im Forum kaum andere Linux-Freaks (die sich mit Linux-Api auskennen) aktiv zu sein, oder ?

Du hast es aber ganz schön drauf und ich versuche immer besser mit der Linux-Api klarzukommen.

Außerdem ist dein Linux-Api-Viewer die beste Erfindung für PureBasic-Linux-Nutzer.

Eine kompakte Dokumentation ist hierbei sehr wichtig.

Eine zeitraubende Internet/Foren- Suche ist nicht toll.
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Magic of GTKCellRenderer :)

Beitrag von ccode_new »

Das hier funktioniert, aber ist total unflexibel. (Den Callback kann man aber auch schwer umgehen, oder ?)

Code: Alles auswählen

ImportC ""
  g_object_set(*Object.GtkObject, property.p-utf8, value.i, term.i = 0)
  g_type_check_instance_is_a(*Instance.GTypeInstance, *Type.GTypeClass)
  gtk_cell_layout_get_cells(*cell_layout)
EndImport

Global NewList SuperRow.i()

ProcedureC ColumnRenderingCallback(*Column.GtkTreeViewColumn, *Renderer.GtkCellRenderer, *Model, *Iter.GtkTreeIter, *UserData)
  Protected XRow.i
  Protected user_str.s, color_str.s
  Protected bgcolor.i, fgcolor.i, row.s, lsize.i, i.i
  
  user_str = PeekS(*UserData, -1, #PB_UTF8)
  
  lsize = Val(StringField(user_str, 1, ":"))
  row = StringField(user_str, 2, ":")
  fgcolor = Val(StringField(user_str, 3, ":"))
  bgcolor = Val(StringField(user_str, 4, ":"))
  
  XRow = Val(PeekS(gtk_tree_model_get_string_from_iter_(*Model, *Iter), -1, #PB_UTF8))
  If FindString(row, "#"+Str(XRow)+"#")
    color_str = "rgb("+Str(Red(bgcolor))+","+Str(Green(bgcolor))+","+Str(Blue(bgcolor))+")"
    g_object_set(*Renderer, "cell-background", UTF8(color_str))
    color_str = "rgb("+Str(Red(fgcolor))+","+Str(Green(fgcolor))+","+Str(Blue(fgcolor))+")"
    g_object_set(*Renderer, "foreground", UTF8(color_str))
  Else
    g_object_set(*Renderer, "cell-background", 0)
    g_object_set(*Renderer, "foreground", 0)
  EndIf
  
EndProcedure

Procedure SetListLineColors(Gadget, col, List row(), fgcolor, bgcolor)
  Protected.i Column, RenderList, Renderer
  Protected list_size.i
  Protected.s user_str.s, data_str.s
  
  ForEach row()
    data_str + "#"+Str(row())+"#"
  Next
  
  list_size = ListSize(row())
  
  user_str = Str(list_size)+":"+data_str+":"+Str(fgcolor)+":"+Str(bgcolor)
  
  Column = gtk_tree_view_get_column_(GadgetID(Gadget), col)
  RendererList = gtk_cell_layout_get_cells(Column)
  
  For i = 0 To g_list_length_(RendererList) - 1
    Renderer = g_list_nth_data_(RendererList, i)
    
    If g_type_check_instance_is_a(Renderer, gtk_cell_renderer_text_get_type_())
      gtk_tree_view_column_set_cell_data_func_(Column, Renderer, @ColumnRenderingCallback(), UTF8(user_str), 0) ;Wie umgehe ich den Callback ?
    EndIf
  Next i
  
  g_list_free_(RendererList)
  
EndProcedure

If OpenWindow(0, 0, 0, 270, 140, "ListViewGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
  ListViewGadget(0, 10, 10, 250, 120)
  For a = 1 To 12
    AddGadgetItem (0, -1, "Item " + Str(a) + " of the Listview")
  Next
  
  AddElement(SuperRow())
  SuperRow() = 2
  AddElement(SuperRow())
  SuperRow() = 11
  
  SetListLineColors(0, 0, SuperRow(), RGB(255,0,0), RGB(255,255,0))
  
  
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Magic of GTKCellRenderer :)

Beitrag von ccode_new »

Hallo Leute,

nach einer Unterhalung im GTK+ (Develop) -IRC-Channels habe ich jetzt die Gewissheit das auch die nicht wissen wie man per CSS-Treeview-Items-Attribute setzt. (bzw. es ist nicht möglich)

Und die Callback-Funktionen haben auch ihren Sinn. :wink:

Man müsste sonst die Eigenschaften in einer Liste beim Erstellen übergeben.

Änderungen sind dadurch aber sehr kompliziert. (daher die Callback-Funktion)
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Omi
Beiträge: 143
Registriert: 25.03.2013 09:59

Re: Magic of GTKCellRenderer :)

Beitrag von Omi »

@ccode_new
Leute, ihr seid zu fleissig - ich komm' nicht mehr hinterher!
Ich muss euch jetzt mal Danken für euren Einsatz.

Ich wollte es Dir gestern schon schreiben - aber der Tag wurde zu kurz:
Ich hab mich mit dem Thema auch schon mal gespielt.
Die Erfahrung:
- Zu viel API-Änderung vertragen die GtkTree-Gadgets nicht, da hier (für Windows-ähnliches-Verhalten) eben ein bestimmtes Model festgelegt ist und sich PB auf dieses verlässt.
Es gibt hierzu auch ein knappes Posting von freak.
- Wagt man zu viel an Änderung, erhöht es nicht gerade Stabilität und die korrekte Funktion (aus Erfahrung mit meinem API-Viewer für Gtk3 und anderen Experimenten :wink: )
Vermutung: PureBasic schiebt die Befehle nicht einfach an die API durch, sondern scheint hierzu auch eine Liste zu erstellen und anhand der betreffenden Befehle zu pflegen. Möglicherweise pflegt auch PB ein eigenes Callback?
Auch die Renderer vertragen nicht jede Änderung oder Ergänzung.
Ich haben mal per API eine interne einfache Drop-Drop-Funktion auf ListIcon-/Tree-Gadgets verwendet (an PB vorbei) um die Items umzusortieren:
Gar wunderliche Dinge geschahen und die Abstürze häuften sich. -> D.h. API und PB waren nicht mehr der gleichen Meinung wo sich denn jetzt die Items befanden und für welches Item die PB-Befehle nun gelten.
D.h. nur vorsichtige Änderungen an der PB-Version oder ALLES über die API.
- Wenn Du für CSS etc. die Attribute in einer Liste fürs Callback mitverwalten möchtes, musst Du auch ans Löschen (aus bestimmten Positionen), Verschieben (per D&D oder per Kommando), Hinzufügen (an bestimmten Positionen) der Items (und Spalten) denken.
Dieser Aufstand und die etwas undurchsichtige Renderer-Attribute je Spalte, -Verhalten und -Einschränkungen + Stabilitätsverlust waren der Grund, warum es mir damals zu viel für das Plus an Nutzen wurde.

ps:
Ich möchte euch mit diesem Posting KEINESWEGS vom Erforschen und Posten der Ergebnisse abhalten. Jede Erkenntnis ist wertvoll, bringt nutzbare Vorgehensweisen und kann Leute von zeitaufwändigen Sackgassen fernhalten.
Ich bin mir auch nicht sicher, ob TreeGadget- Zellen, Zeilen und Spalten vom ständigen Gtk3-Slalom so betroffen sind - es kann sein, dass uns diese Grundfunktionen dann doch länger erhalten bleiben, im Gegensatz zu den
Hinter- / Vordergrund-Funktionen der Gadgets-Basics.
PureBasic Linux-API-Library: http://www.chabba.de
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Magic of GTKCellRenderer :)

Beitrag von ccode_new »

Hallo!

Um so tiefer ich in die GTK3-Api einsteige, um so mehr hasse ich sie.

Ich wollte mal etwas damit ausprobieren: "gtk_style_context_add_region"
Die Api sagt:
has been deprecated since version 3.14 and should not be used in newly-written code.

Wie kann ich selber den Hintergrund bei einem Gadget anpinseln ? (Ich glaube das wird kompliziert )

Beispiel: TreeView (ListViewGadget)

CSS: "box* {background-image: linear-gradient(yellow, green); background-repeat: no-repeat; color: green; } .view:selected {background: yellow}"

Damit wird aber nur immer ein Hintergrundbild auf eine einzige Zeile erstellt und immer wieder wiederholt.
Wie bekomme ich so etwas als gesamten Hintergrund ?

Oder wie bekomme ich mit der Hardcore-Methode Zugriff zum zeichnen ?
(Und noch besser: Wie kann ich dabei nur den Hintergrund beeinflussen ?)

Code: Alles auswählen

g_signal_connect_(GadgetID(0), "draw", @draw_callback(), #Null)

Procedure draw_callback(*widget.GTKWidget, *cr, *user_data)
    Protected.i width, height
    Protected color.GdkRGBA
    Protected *context
    
    *context = gtk_widget_get_style_context(*widget)
    width = gtk_widget_get_allocated_width(*widget)
    height = gtk_widget_get_allocated_height(*widget)
    gtk_render_background(*context, *cr, 0, 0, width, height)
    gtk_style_context_get_color (*context, gtk_style_context_get_state(*context), @color)
    gdk_cairo_set_source_rgba (*cr, @color)
    ;....
    cairo_fill(*cr)
  EndProcedure
@Omi:

Also laut dem tollen "Inspekteur-Tool" ist die GTK-Treeview-Structure folgende:

GtkScrolledWindow (Stilklasse: frame)
->darin befindet sich das: GtkTreeView (Stilklasse: view)
..
Das GtkTreeView enthält dann eine "GtkListStore".
In dieser Liste sind die Item-Texte enthalten als (gchararray)

Außerdem:
GtkTreeSelection,
GtkTreeViewColumn -> GtkCellAreaBox -> GtkCellRendererText

(Der enthaltene GtkButton ist bei einem ListViewGadget deaktiviert)

Das GtkScrolledWindow enthält außerdem (neben dem GtkTreeView)
eine GtkScrollbar (bzw. 2 davon)

Anbei:
Wenn man den Hintergrund als Bild über "gtk_style_context_add_provider_for_screen" setzt. (Also für alle Gadgets) hat man den gleichen Grafikbug wie bei SetGadgetColor() für die Hintergrundfarbe des Listviews. :wink:
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Omi
Beiträge: 143
Registriert: 25.03.2013 09:59

Re: Magic of GTKCellRenderer :)

Beitrag von Omi »

Moin ccode_new,

da das ComboBoxGadget auch auf dem TreeView basiert und ebenso bockig ist, fürchte ich langsam da es hier generell etwas hakt!

Ich hab die Hintergrundsache vor längerer Zeit mit einem EditorGadget versucht (das mal funktioniert und mal nicht):
http://www.chabba.de/Linux/EditorGadget ... CssGtk3.pb und sicherlich noch keine optimale CSS-Anweisungen enthält. Es müsste prinzipiell auf TreeGadgets die selben Funktionsfähigkeit haben. Vielleicht hilft's für neue Erkenntnisse.

Prinzipiell könntest Du auch noch im Gtk3-Demo (Abteilung CSS (oder so) in älteren, Theming in neueren Versionen) stöbern, in dem auch der C-Sourcecode einsehbar ist:
Installation müsste so funktionieren: sudo apt-get install gtk-3-examples
Zum Starten wird entweder ein Menueintrag erstellt oder aus dem Terminal mit gtk3-demo.

Hier sieht man mal was eigentlich alles möglich ist wenn man damit umgehen kann! Vom Wissensstand dieser Programmierer sollte etwas mehr in der Hilfe zum Gtk landen. Aber scheinbar ist die 'Verunstaltung' des Basis-Designs von Anwendungsprogrammieren auch dort nicht so gewünscht und deshalb der Zugang nur für Hartnäckige möglich :wink: .

Grüße und schönen Sonntag
PureBasic Linux-API-Library: http://www.chabba.de
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Magic of GTKCellRenderer :)

Beitrag von ccode_new »

Grüß dich!
Omi hat geschrieben:Prinzipiell könntest Du auch noch im Gtk3-Demo (Abteilung CSS (oder so) in älteren, Theming in neueren Versionen) stöbern, in dem auch der C-Sourcecode einsehbar ist:
Installation müsste so funktionieren: sudo apt-get install gtk-3-examples
Zum Starten wird entweder ein Menueintrag erstellt oder aus dem Terminal mit gtk3-demo.
Vielen Dank! Das kannte ich bisher auch noch nicht. Es ist eine schöne Sammlung.

Mal sehen ob sich da etwas umsetzen lässt.
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Antworten