How do I add ScrolledWindow support to a custom Widget in GtkMM? - gtk

I am writing a custom widget for Gtkmm that is supposed to display a huge dataset (imagine something like a 4096x256 character datasheet).
Mostly for reasons of elegance, but also for a possible usage in a Glade/Gtk-Builder editor, I want this widget to support ScrolledWindow natively, that is, once it is set as the child of ScrolledWindow, it is recognized as a scrollable widget, allowing to set horizontal and vertical Adjustment objects on it, which it can subsequently tamper with.
It appears to do so, I need to do something like this in the constructor of my widget:
// get Gtk C type from wrapper class
GtkWidget* gwidget = this->gobj();
// imagine code here that magically creates a gobject signal,
// that we can catch in C++.
// this is actually the part which I don't know how to do.
guint my_signal = magic_way_to_create_this_signal(
&MyClass::rainbow_unicorn_signal_handler);
// make ScrolledWindow recognize this window as scrollable
GTK_WIDGET_GET_CLASS(gwidget)->set_scroll_adjustments_signal = my_signal;
Later on, the signal emitted by ScrolledWindow when the widget is added needs to be caught by my Widget through a signal proxy method or something? I have no idea.
How can I do this?

The 'magic_way_to_create_this_signal' is g_signal_new(). You call it in your widget's my_widget_class_init() function which is part of the GObject way of defining a class. I'm not exactly sure what the equivalent is in Gtkmm.
See also the footnote in the GTK docs, where it is explained why making a widget natively scrollable is such a hassle.
You could also put your widget into a Gtk::Viewport which adds scrolling capabilities to its child widget.

Related

Why Container and Column are not const flutter?

Please see the question above. I looked the documents, but didn't find any answers.
It depends on the child/ children if they don't have static value it can't be const. if the have hardcoded or static values then it must be const
Why do we need to use const widgets in flutter?
It is recommended to use const constructors whenever possible when creating Flutter widgets. The reason is the performance increase since Flutter can save some calculations by understanding that it can reuse that widget from a previous redraw in the current one since it is a constant value.
Flutter has a special treat for when the instance of a widget doesn't change: it doesn't rebuild them.
Consider the following:
Foo( child: const Bar( child: Baz() ), )
In the case of the build method being called again (setState, parent rebuild, Inheritedwidget...), then due to the const for Bar subtree, only Foo will see its build method called.
The bar will never get rebuilt because of its parent because Flutter knows that since the widget instance didn't change, there's nothing to update.
Why can't we make a Container widget and Column widget const?
You cannot make const a Container as the Constructor of Container is not const that's why it won't let you do it.
This is allowed in the form of making the children const. Allowing const on the children means they will not rebuild if they are not dynamic.
Flutter doesn't rebuild widgets that are marked created through const constructor and the main part of the flutter widgets supports const constructors. Except for Column and Row and other multi-child layout widgets.
Do we really need to make multi-child layout widgets const?
The Column/Row themselves do not need to be const as they're only for laying out the widgets, it's the children that need to const. The same behavior applies to the rest of the Multi child layout widgets.
These might be for lots of reasons. Instead of listing all of them here. I will show you how to explore each one of them on your own so that you can orient your investigations based on your needs. Below, are the steps I went through to figure out why the container is non-const. (you can do this with any other Widget or constructor)
Explore the source code
Open the fuller package (in VSCode): [flutter_location]/packages/flutter/lib/src/widgets/container.dart
Run flutter pub get
Look for the Container constructor
Add the const keyword in front of it
All elements that prevent the Container from being a const constructor, quite a few, will show errors!
To explore multiple widgets at once just open the entire folder [flutter_location]/packages/flutter. Then run flutter pub get.

Methods vs separate classes for widgets in Flutter?

I heard a lot about "flutter method-widgets is considered anti-pattern". But why? Elements don't care about widgets' parameters (equal or not). Only const widgets save rebuilds. So why do I have to separate them to relatively verbose classes, when I could just
Widget _buildMe() => Container() // here is some widget, which depends on other params (so it cannot be const)
inside my StatelessWidget class.
Update: I also assume that methods don't depend on InheritedWidget. In that case it's obvious, that they should be separated.
It's an anti-pattern, because in some cases it leads to unnecessary rebuilds (depending on Inherited widget for example). But in general you can use it, if you use it wisely (2-3 methods in class don't make any harm).

Flutter - best approach to create TabledToggledButtons?

I would like my toggle buttons to be layout in a table, and not as a single row.
The number of toggle buttons is not static -
that is upon init I load a resource which contains a list of all the texts that should become the toggle buttons.
Looked at a number of approaches, each has its issues:
Create a list of ToggleButtons and a list of lists of bools to store the appropriate selected state as a data structure to divide the toggle buttons into a number of rows. The problem with this approach is in the implementation of the onPressed method - how to get a reference to the appropriate element in the list of lists of bools? Or in other words - how to get a reference to ToggleButtons object from within the onPressed method?
Use key property to pass the index of the current ToggleButtons. It is not intended for this purpose, so it is a bad practice, also again, there seems to be no straightforward way to access the key property from the onPressed method.
Extend the ToggleButtons class, and specifically override its build method. This is considered an anti-pattern in Flutter in general. Specifically In this approach, as we want all the functionality to remain the same, and change only the internal Row -> Table widget generation in the build method, it looks like we would have to duplicate all the code of this method, which is a bad idea as it might brake things as it changes in future versions of this widget
Create a table of checkbox / switch widgets as an alternative, which should work easily, but I want the look & feel of toggle buttons, not checkboxes or switches :)
I must be missing something simple!
After posting this I have a new idea :)
A table of FlatButtons! Will be probably possible to achieve similar UI to ToggleButtons. Will try it in a bit.
I would still love to hear other suggestions regarding ToggleButtons.
Try using SwitchListTile.
The entire list tile is interactive: tapping anywhere in the tile toggles the switch. Tapping and dragging the Switch also triggers the onChanged callback.
To ensure that onChanged correctly triggers, the state passed into value must be properly managed. This is typically done by invoking State.setState in onChanged to toggle the state value.
The value, onChanged, activeColor, activeThumbImage, and inactiveThumbImage properties of this widget are identical to the similarly-named properties on the Switch widget.
The title, subtitle, isThreeLine, and dense properties are like those of the same name on ListTile.
The selected property on this widget is similar to the ListTile.selected property, but the color used is that described by activeColor, if any, defaulting to the accent color of the current Theme. No effort is made to coordinate the selected state and the value state; to have the list tile appear selected when the switch is on, pass the same value to both.
The switch is shown on the right by default in left-to-right languages (i.e. in the ListTile.trailing slot) which can be changed using controlAffinity. The secondary widget is placed in the ListTile.leading slot.
To show the SwitchListTile as disabled, pass null as the onChanged callback.

Build Context and state object in flutter

The newly created State object is associated with a BuildContext. This
association is permanent: the State object will never change its
BuildContext. However, the BuildContext itself can be moved around the
tree along with its subtree.
what does this statement trying to say? i find it quite subtle. it is from the official documentation of flutter
There are a lot of core concepts here, first of all you need to understand how flutter render the widgets, ill try to make a summary.
At run time, flutter internally manage three trees in order to achieve the high performance: Widget tree, Element tree and RenderObject tree.
I'm not going to get deep into this since is complicated but basically each tree has different responsibilities:
Widget: describe the configuration for an Element. It handle
Configuration.
Element: an instantiation of a Widget at a particular location in the
tree. It manage Life cycle.
RenderObject: handles size, layout, etc. It handle render and
painting aspects.
So, for every widget, Flutter builds a corresponding Element and build the Element Tree.
For Stateless widgets, the relation between widget and the corresponding element is trivial, but for Stateful widgets the underlying Element structure looks a little different. Those elements add a state object, which holds the mutable part of the configuration, a color for example.
The other thing that you should know is that BuildContext is actually a Element.
With that in mind, the meaning of this:
The newly created State object is associated with a BuildContext. This
association is permanent: the State object will never change its
BuildContext. However, the BuildContext itself can be moved around the
tree along with its subtree.
Is trying to say that when you build a Stateful widget, flutter is going to build a BuildContext (an element that hold the widget position, among other properties) and that contexts will hold the mutable State object.
Then the buildContext (element) itself can change (moved on the tree for example), but the thing that never is going to happen is that changing the state object will change the BuildContext. And that's why you can change, for example, the widget color or any mutable property on State object, and it will never change the element position in the tree.
Is a really interesting topic but is not simple. I highly recommend you to check this video and this article that have a deep explanation into the this.
Hope it helps!

Adding css class names to the contents of Cells in a gwt CellTable

I want to add style classes to elements in a cell (or the td itself) that will change depending on the state of the data in the cell. For example, the cell might have color: red when the data is unsaved, color: blue while the data is being saved, and color: black once the save completes successfully. Code external to the Cell will need access to change the class names, once callbacks are fired, etc.
I have achieved something like this with a hack in my Cell that gets the Element from onBrowserEvent and adds attributes there. I can set the initial style in render and then change it as needed in onBrowserEvent, and even keep track of that element so that external code can use it. This is incomplete, because I can't get the element until onBrowserEvent is called, and annoyingly hacky because I have to set the style in two different places.
What's a better way to achieve this effect without re-rendering the entire table whenever the state of a cell changes?
I found something like
table.setRowStyles(new RowStyles() {
#Override
public String getStyleNames(Contact row, int rowIndex) {
if (row.name.startsWith("J")) {
return "bold";
}
return null;
}
});
which should work in GWT 2.4 to resolve your matter.
The disappointing answer here is that you can't have the best of both worlds - static, all-at-once-rendering, AND dynamic, change-one-element-updating. The only way to change the style of a single cell, within the methods provided by CellTable et al, is to rerender the whole table.
In my own code I've kind of formalized the hacks I made to update single cells at a time, by setting the DOM id of a div rendered to each table cell. Then I can use getElementById and proceed from there. I still avoid the overhead of a full widget. It's a little clunky, but hidden behind a nice interface it's not too bad.