Closed chip closed 1 month ago
Thanks for the kind words.
I was able to override the background_color
with no problem in the code below (has red background with half transparency). One thing to keep in mind is background_color_column
must be included inside table
as the last column, and each model in the cell_rows
data-bound model collection (e.g. self.animals
) must have a background_color
method that returns the color as rgb hash, rgba hash, rgb array, rgba array, hexadecimal string, hexadecimal number, or color name string.
require 'glimmer-dsl-libui'
class BasicTableColorRedBackground
Animal = Struct.new(:name, :sound, :mammal)
class AnimalPresenter < Animal
def name_color
color = case name
when 'cat'
:red
when 'dog'
:yellow
when 'chicken'
:beige
when 'horse'
:purple
when 'cow'
:gray
end
[name, color]
end
def sound_color
color = case name
when 'cat', 'chicken', 'cow'
:blue
when 'dog', 'horse'
{r: 240, g: 32, b: 32}
end
[sound, color]
end
def mammal_description_color
color = case name
when 'cat', 'dog', 'horse', 'cow'
:green
when 'chicken'
:red
end
[mammal, 'mammal', color]
end
def image_description_color
color = case name
when 'cat', 'dog', 'horse'
:dark_blue
when 'chicken'
:beige
when 'cow'
:brown
end
[img, 'Glimmer', color]
end
def img
# scale image to 24x24 (can be passed as file path String only instead of Array to avoid scaling)
[File.expand_path('../icons/glimmer.png', __dir__), 24, 24]
end
def background_color
{r: 255, g: 0, b: 0, a: 0.5}
end
end
include Glimmer
attr_accessor :animals
def initialize
@animals = [
AnimalPresenter.new('cat', 'meow', true),
AnimalPresenter.new('dog', 'woof', true),
AnimalPresenter.new('chicken', 'cock-a-doodle-doo', false),
AnimalPresenter.new('horse', 'neigh', true),
AnimalPresenter.new('cow', 'moo', true),
]
end
def launch
window('Animals', 500, 200) {
table {
text_color_column('Animal')
text_color_column('Sound')
checkbox_text_color_column('Description')
image_text_color_column('GUI')
background_color_column # must always be the last column and always expects data-binding model attribute `background_color` when binding to Array of models
cell_rows <= [self, :animals, column_attributes: {'Animal' => :name_color, 'Sound' => :sound_color, 'Description' => :mammal_description_color, 'GUI' => :image_description_color}]
}
}.show
end
end
BasicTableColorRedBackground.new.launch
The background_color
method on the model can return a different value for every model object instance if you want to vary the background color, you can pass it directly to the model as an extra attribute or have it calculated based on other attributes, like an index.
Here is an example where we alternate colors for even and odd rows between red and gree.
require 'glimmer-dsl-libui'
class BasicTableColorAlternatingBackground
Animal = Struct.new(:name, :sound, :mammal, :index)
class AnimalPresenter < Animal
def name_color
color = case name
when 'cat'
:red
when 'dog'
:yellow
when 'chicken'
:beige
when 'horse'
:purple
when 'cow'
:gray
end
[name, color]
end
def sound_color
color = case name
when 'cat', 'chicken', 'cow'
:blue
when 'dog', 'horse'
{r: 240, g: 32, b: 32}
end
[sound, color]
end
def mammal_description_color
color = case name
when 'cat', 'dog', 'horse', 'cow'
:green
when 'chicken'
:red
end
[mammal, 'mammal', color]
end
def image_description_color
color = case name
when 'cat', 'dog', 'horse'
:dark_blue
when 'chicken'
:beige
when 'cow'
:brown
end
[img, 'Glimmer', color]
end
def img
# scale image to 24x24 (can be passed as file path String only instead of Array to avoid scaling)
[File.expand_path('../icons/glimmer.png', __dir__), 24, 24]
end
def background_color
if index.even?
{r: 255, g: 0, b: 0, a: 0.5}
else
{r: 0, g: 255, b: 0, a: 0.5}
end
end
end
include Glimmer
attr_accessor :animals
def initialize
@animals = [
AnimalPresenter.new('cat', 'meow', true, 0),
AnimalPresenter.new('dog', 'woof', true, 1),
AnimalPresenter.new('chicken', 'cock-a-doodle-doo', false, 2),
AnimalPresenter.new('horse', 'neigh', true, 3),
AnimalPresenter.new('cow', 'moo', true, 4),
]
end
def launch
window('Animals', 500, 200) {
table {
text_color_column('Animal')
text_color_column('Sound')
checkbox_text_color_column('Description')
image_text_color_column('GUI')
background_color_column # must always be the last column and always expects data-binding model attribute `background_color` when binding to Array of models
cell_rows <= [self, :animals, column_attributes: {'Animal' => :name_color, 'Sound' => :sound_color, 'Description' => :mammal_description_color, 'GUI' => :image_description_color}]
}
}.show
end
end
BasicTableColorAlternatingBackground.new.launch
Here is another example where the background color is passed to each model as an extra attribute.
require 'glimmer-dsl-libui'
class BasicTableColorCustomBackground
Animal = Struct.new(:name, :sound, :mammal, :background_color)
class AnimalPresenter < Animal
def name_color
color = case name
when 'cat'
:red
when 'dog'
:yellow
when 'chicken'
:beige
when 'horse'
:purple
when 'cow'
:gray
end
[name, color]
end
def sound_color
color = case name
when 'cat', 'chicken', 'cow'
:blue
when 'dog', 'horse'
{r: 240, g: 32, b: 32}
end
[sound, color]
end
def mammal_description_color
color = case name
when 'cat', 'dog', 'horse', 'cow'
:green
when 'chicken'
:red
end
[mammal, 'mammal', color]
end
def image_description_color
color = case name
when 'cat', 'dog', 'horse'
:dark_blue
when 'chicken'
:beige
when 'cow'
:brown
end
[img, 'Glimmer', color]
end
def img
# scale image to 24x24 (can be passed as file path String only instead of Array to avoid scaling)
[File.expand_path('../icons/glimmer.png', __dir__), 24, 24]
end
end
include Glimmer
attr_accessor :animals
def initialize
@animals = [
AnimalPresenter.new('cat', 'meow', true, {r: 134, g: 83, b: 24}),
AnimalPresenter.new('dog', 'woof', true, {r: 134, g: 183, b: 224}),
AnimalPresenter.new('chicken', 'cock-a-doodle-doo', false, {r: 34, g: 183, b: 24}),
AnimalPresenter.new('horse', 'neigh', true, {r: 34, g: 183, b: 124}),
AnimalPresenter.new('cow', 'moo', true, {r: 34, g: 83, b: 24}),
]
end
def launch
window('Animals', 500, 200) {
table {
text_color_column('Animal')
text_color_column('Sound')
checkbox_text_color_column('Description')
image_text_color_column('GUI')
background_color_column # must always be the last column and always expects data-binding model attribute `background_color` when binding to Array of models
cell_rows <= [self, :animals, column_attributes: {'Animal' => :name_color, 'Sound' => :sound_color, 'Description' => :mammal_description_color, 'GUI' => :image_description_color}]
}
}.show
end
end
BasicTableColorCustomBackground.new.launch
I hope that helps.
If you need further help, please share your code so that I am better able to help you.
You can close the issue if you think it is resolved. Otherwise, feel free to ask further questions.
Thanks so much for your prompt and thorough reply. The examples you provided there and from running glimmer examples
has been incredibly helpful! 👍🏻
Yes, under normal circumstances I'm able to override the background_color
, but not when the row is "selected" (or clicked). My original code was disorganized, so instead I ran your example code above to show a before and after.
This shows when table initially renders. All is well here:
And here the background is blue when I click on the last row containing "cow", "moo", "mammal" (sorry, my cursor is hidden in this screenshot):
It looks like the native widget behavior takes over from there upon selection. I tried a number of approaches using on_row_clicked
and on_selection_changed
to determine the row index and from there attempt to override the text color
or background_color
, all to no avail.
Any pointers are greatly appreciated. I'll be happy to close if this isn't possible. Thanks again for your help!
Yeah, that is the Selection Background Color, which is different. It comes from the Operating System Theme, and it cannot be overridden by design given LibUI is a Native GUI Toolkit that aims to conform to the Operating System Theme and Look & Feel to build Graphical User Interfaces that are more familiar, intuitive, and user-friendly to users who already know how the operating system apps look and feel.
That said, LibUI allows you to build your own non-native table custom control from scratch on top of area
. Here is an example of a button custom control and label custom control built from scratch on top of area
: https://github.com/AndyObtiva/glimmer-dsl-libui/blob/master/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#area-based-custom-controls
Of course, that means, the code would have to manage all table features, like selection management, and generation of table rows based on model data.
Here is another example of doing something like this to render graphs and charts from scratch, and provide them as new custom controls that could be reused in multiple apps: https://github.com/AndyObtiva/glimmer-libui-cc-graphs_and_charts
If a table custom control was built to facilitate customizing row background selection color, it would only require effort the first time it is built, but afterwards, it could be used as a custom control component.
Alternatively, you can use a different toolkit like Glimmer DSL for SWT, which provides a way to override the OS selection background color according to this StackOverflow post: https://stackoverflow.com/questions/64502873/how-to-change-swt-table-item-selection-background-color#:~:text=The%20selection%20colour%20is%20normally,yourself%20in%20the%20erase%20method.
Also, you could try to use non-native widget toolkits like Glimmer DSL for Tk, Glimmer DSL for FX, Glimmer DSL for Swing, and Glimmer DSL for JavaFX if you would like to have your own table selection color.
I've never personally had this requirement, as business projects typically like to conform to the native look and feel of the OS. I worked at a company once that hated that the Swing GUI Toolkit made developers customize the look and feel everywhere instead of simply conforming to the OS standards, so they used SWT instead, another native GUI Toolkit (like LibUI), and that made their business apps a lot more user friendly and simpler to build for their users. Going against the OS look and feel is generally not recomended in desktop development, and is not very common. It's a huge benefit in desktop development not to have to customize the look and feel completely, yet only in very rare circumstances (which is why LibUI supports building custom controls on top of area
), as conforming to OS standards enables much higher productivity in building desktop apps over web apps, which waste a lot of time on look and feel. If someone is trying to build desktop apps as web apps, they're missing the whole point that enables the much higher productivity in desktop development.
I hope I answered your question sufficiently.
Great explanation. Yeah, I agree it makes good sense to accept the native behavior and work within those constraints. I may have been trying to over-optimize a bit here. 😃
What you've provided with this toolkit is greatly appreciated. You've been quite generous with your time and examples. Thank you again for all of your help with my request!
You're welcome
First off, THANK YOU for this amazing project. It's truly special! 😄
I tried overriding #background_color of your BasicTableColor example and it still returned the default blue on MacOS, so I was curious if there's a workaround?
Thanks again.