Using flutter inspector I'm not able to find a list of widget's properties like font size, font family, border color, padding, margin ...
For example, in a Text widget the available properties are textDirection, textAlign, size, and a few more, like in screenshot below:
I would like to see all computed properties, like browsers do:
Of course they are different tools, but i would like to know if there is a way to check more properties.
I also found a code-based solution, to access widget properties after it has been rendered, like in this question:
How to get the TextFormField text color,fontsize, etc using controller in flutter?
Is that the best way to achieve the result? Is it possible to use Keys in a way which allows to access widget properties without using a custom widget (i would like to save the reference to a Text, Row, etc. widgets and print all their properties)?
I also tried to use toDiagnosticsNode and toStringDeep methods as follows (_textWidget is of course a Text widget created above, this code is called when i click a button):
var test = _textWidget.toDiagnosticsNode().getProperties();
if (test != null && test.isNotEmpty) {
test.forEach((element) {
print(element.toStringDeep());
});
}
Is it possible to play a bit with a recursive function to get all the properties? All i can see with that code is the text displayed.
Related
How can we show/hide widget inside another widget in flutter?
I have list of question which are inside list view builder I want to hide questions on user answer selection.
if you have all equations in question[] and whether to show them in show[], you could place into listbuild
return (bool[index] ? Card(child:Text(question[index])) : Container())
This returns the card in bool is true and the empty (not displayed container) otherwise.
(I think the other answer would do the trick too)
Another option you can consider though is using the Visibility widget to wrap the "question" widget and toggle the visible property based on a bool. To make this (or the above solution) work, you'd want to update the value of this bool using e.g. setState on the method called when,as you say, "user answer selection" happens.
Of course, if you have a more complicated application it might make more sense to use Provider for state management and wrap all of this in a Consumer.
I am writing a custom widget using gtkmm and I would like to use the standard selection colour when part of my widget is selected. For example when you select text in a text box, the background colour goes (for me) dark blue, so I want to obtain this same dark blue colour.
I have tried this, but I only get black or white, not the actual colours in use:
bool MyWidget::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
Gdk::Cairo::set_source_rgba(cr,
get_style_context()->get_color(Gtk::STATE_FLAG_SELECTED));
}
What is the correct way to obtain the standard colours with gtkmm, such that if the user changes their colour theme, the changes will also be reflected here?
Or is it considered best practice to define some new CSS styles which inherit from the standard system ones, so that people can override colours for just my widget if they desire, without affecting others?
Turns out the answer to this is that what I was doing in the question was correct, except there were no styles applied to the widget so the colours were just black and white.
I had to add this in the widget's constructor:
this->get_style_context()->add_class(GTK_STYLE_CLASS_ENTRY);
To get text entry styles. Of course this made render_background() as suggested by ebassi render a text entry background instead, which isn't what I wanted (I just wanted a solid colour.) So instead I changed the above line (in the constructor) to:
this->get_style_context()->add_class(GTK_STYLE_CLASS_DEFAULT);
And in my render function, temporarily set text-entry styles just to get the colour:
auto cxStyle = this->get_style_context();
cxStyle->context_save();
cxStyle->add_class(GTK_STYLE_CLASS_ENTRY);
Gdk::Cairo::set_source_rgba(cr, cxStyle->get_background_color(Gtk::STATE_FLAG_SELECTED));
cr->fill();
cxStyle->context_restore();
This way I was able to obtain the text selection colour and fill a rectangle behind the area of my custom widget that should be shown as currently selected.
I couldn't use render_background() here because it would have drawn the background of a text control which I don't want, I just wanted a solid filled rectangle.
The proper way to render the background of a widget is to use gtk_render_background(). This function will take into account widget state and style.
Your code above becomes:
bool
MyWidget::on_draw (const Cairo::RefPtr<Cairo::Context>& cr)
{
double w = get_allocated_width(), h = get_allocated_height();
Glib::RefPtr<Gtk::StyleContext> context = get_style_context();
context->render_background(cr, 0, 0, w, h);
return true;
}
This way your widget will always be updated to reflect the theme.
If you want to control the color and style of your widget you should use an additional Gtk::StyleProvider for your application to load a custom CSS fragment with the desired style classes.
I would like to print a GWT widget which extends Composite. This widget is composed of a grid whose cells are built with a ListDataProvider. When the user clic on a button print, the widget to print is built. Once this is done, I launch the print:
Element element = widgetToPrint.getElement();
String content = element.getInnerHTML();
print(content);
public static native boolean print(String content)
/*-{
var mywindow = window.open('', 'Printing', '');
mywindow.document.write('<html><head><title>Test</title>');
mywindow.document.write('<link rel="stylesheet" href="/public/stylesheets/ToPrintWidget.css" type="text/css" media="all"/></head><body>');
mywindow.document.write(content);
mywindow.document.write('</body></html>');
mywindow.print();
return true;
}-*/;
So, here is my problem:
The window which is opened by this method contains the core of the widget (built by the UI Binder), but some children are missing...
If I look inside the ListDataProvider and its related FlowPanel, the data are consistent, i.e. I've got several item in my list and in the flowPanel.
Consequently, it should be visible on the printing window...
I thought that maybe the problem was related to the method used to print the widget, so I also tried to add this widget into a dialogbox just before launching the print, to see if the widget was properly built... and it was.
So my widget displays well on a dialogbox, but if I try to give its innerHTML to the print method, by using getElement(), some widgets are missing... I've the feeling that the widgets which should have been built when the ListDataProvider changes are not properly set in the DOM... Somehow it works when I add the widget to a regular component, but it doesn't work when I have to give directly its innerHTML...
Do you have any idea ?
Thanks in advance.
Widgets are not just the sum of their elements, and DOM elements are not just the string that they are serialized to. Widgets are the element, and all events sunk to the dom to listen for any changes or interactions by the user. Elements then have callback functions or handlers they invoke when the user interacts with them.
By serializing the element (i.e. invoking getInnerHTML()), you are only reading out the structure of the dom, not the callbacks, and additionally not the styles set by CSS. This probably shouldn't be expected to work correctly, and as your experience is demonstrating, it doesn't.
As this is just a print window you are trying to create, event handling is probably not a concern. You just want the ability to see, but not interact with, the content that would be in that set of widgets. Styles are probably the main problem here then (though your question doesn't specify 'some children are missing' doesn't tell us what is missing, or give us any more clues as to why...) - you are adding one stylesheet in your JSNI code, but CellTable (which I assume you are using since you reference ListDataProvider) needs additional CssResource instances to appear correctly. I'm not sure how you can hijack those to draw in a new window.
Are you only using this to print content, not to let the user directly interact with the data? If so, consider another approach - use a SafeHtmlBuilder to create a giant, properly escaped string of content to draw in the new window.
String content = element.toString();
This will include all hierarchy elements in the node.
Just a reminder, all the GWT handlers will not work, and you have to sink all the events using DOM.
You might want to grab the outer HTML rather than the inner one.
GWT unfortunately has no getOuterHTML, but it's relatively easy to emulate.
If your widget is the only child within an element, then simply get the inner HTML of the parent element (w.getElement().getParentElement().getInnerHTML())
Otherwise, clone your widget's node add it to a newly created parent element, from which you'll be able to get the inner HTML:
DivElement temp = Document.get().createDivElement();
temp.appendChild(w.getElement().cloneNode(true));
return temp.getInnerHTML();
First thank you for your answers, it helped me to work out this problem.
I've almost solve the problem:
First, I do not use ListDataProvider anymore, because it wasn't clear for me when and how the view was refreshed. Instead I add my widgets by hand, which makes sense since, they are not going to move anyway.
Then, I define the style of my widgets using a common CSS stylesheet. However, in order to do it, I can't rely on CssResource, which was the way I was used to do it with GWT. I think that this comes from the JS method which gets lost by this kind of styles... Instead, I have to specify everything in a static CSS stylesheet, and to give it to the JS.
It works perfectly well, ie, I have my widgets, with thei styles, and I can print it.
But...
The color of some widgets depends on the color of the object that they represent. Consequently, I cannot write a generic CSS stylesheet... And as I said, I can't add a style using CssResource... Do you have any ideas on the way to handle that ?
To make sure I'm clear on the way I'm adding styles, here is an example:
Label l = new Label("Here is a cell in my grid to be printed");
l.addStyleName("PrintLineCell-kind_1");
With, in a public CSS stylesheet:
.PrintLineCell-kind_1{
background-color: red;
}
I hope there is a better way than to write 300 styles to cover 300 different colors...
Many dojo form widgets, like DateTextBox will style themselves in red (claro theme) with an "!" to indicate that the field isn't valid after focus. I can't seem to get this type of styling to work with the Select widget. I have the value set to required, but if the user leaves it in the default state, blank, then it remains unstyled.
I tried to test this programmatically:
wigs = dijit.findWidgets(node);
for( i = 0; i < wigs.length; i++ ) {
wigs[i].focus();
}
This triggers validation on several other widgets and they are styled appropriately, but not he Select widgets. Anyone know how to make it obvious that those select widgets are not validating?
Oh, and wigs[i].isValid() is definitely false for those select widgets.
The styles used by FilteringSelect in these circumstances still use the error styles from ValidationTextBox; this isn't the case for Select, and it looks as if there are no styles for .dijitSelectError in any of the themes. I'm thinking Select may not have initially supported any validation so that might be why.
So you'd have to add your own styles for this to work. Also note that there is no node with the dijitValidationIcon class in Select's template, which is what's responsible for the '!' in those other widgets.
I am creating a widget and I want to be able to have the user select the size of the widget in a menu during the configuration activity. My problem is that in the appwidget-provider meta data xml, the block size is already set before the configuration activity is already entered. I need to be able to reset the info of the widget, which contains the block size (minHeight, minWidth), without having to add separate widgets of different sizes. Any ideas?
You cannot do this. It is an Android limitation. Create several widgets with different sizes, name them like "YourWidget (small)", "YourWidget (large)", etc. Or "YourWidget 1x1" and "YourWidget 2x1". You'll need several nearly identical appwidget-provider xml...
Since you'll need also nearly identical provider and configuration classes, define a base classes with all needed code there, and then inherit from them, something like this:
public class WidgetProvider2x1 extends WidgetProvider {
#Override
int getWidgetStyle() {
return WidgetProvider.WIDGET_STYLE_2x1;
}}
call getWidgetStyle() in the base class when you need to know the size of your widget.