Restricting the OptionGroup width in Vaadin - css

I have a couple of OptionGroups with very long captions that run across the width of the page, which looks very bad. I tried restricting the width of the OptionGroup using setWidth and via CSS, and also tried restricting the width of the parent container; all without effect.
So I made a grid layout with an option group in the first column (spanning all rows), and individual labels for the captions in the second column (one per row). However, in case the captions span multiple lines (which they do in my case), this leads to the radio buttons / checkboxes no longer being aligned to the captions. (Regrettably, I'm not allowed to post images.) For instance,
(o) This is a multiline
(o) caption
This is another multiline
caption
I resolved this by creating one OptionGroup per label, and adding each option group in the first column:
(o) This is a multiline
caption
(o) This is another multiline
caption
Clearly, in case of radio buttons, this means multiple buttons can be selected at the same time, since they are no longer linked via a single OptionGroup. Therefore, I registered listeners which, each time a button is selected, de-select all other buttons. And this brings me to my problem; since this "unchecking" is done at the server side, there will unavoidably be some lag, meaning that for some time, multiple radio buttons will appear selected at the client side.
Any ideas on how to resolve this? I only started working with Vaadin recently, so I'm far from an expert. Is there some simple way of restricting the caption width (some magical undocumented CSS class), or do I need to extend / adapt the client-side widget implementation?
Thanks,
William

What you need is FlexibleOptionGroup add-on.
Here is an example implementation:
#Override
protected void init(VaadinRequest request) {
Container cont = new IndexedContainer();
cont.addContainerProperty("caption", String.class, "");
// very long strings in the following setValue() methods
cont.getContainerProperty(cont.addItem(), "caption").setValue("I have...");
cont.getContainerProperty(cont.addItem(), "caption").setValue("So I ma...");
FlexibleOptionGroup fog = new FlexibleOptionGroup(cont);
fog.setCaption("FlexibleOptionGroup:");
fog.setItemCaptionPropertyId("caption");
fog.setMultiSelect(true); // force using CheckBoxes
VerticalLayout fogLayout = new VerticalLayout();
Iterator<FlexibleOptionGroupItemComponent> iter;
iter = fog.getItemComponentIterator();
while(iter.hasNext()) {
// OptionGroupItem part (CheckBox or RadioButton)
FlexibleOptionGroupItemComponent fogItemComponent = iter.next();
// CustomComponent part
Label caption = new Label(fogItemComponent.getCaption());
caption.setWidth(400, Unit.PIXELS);
fogLayout.addComponent(new HorizontalLayout(fogItemComponent, caption));
}
setContent(fogLayout);
}
The above code produces:

Related

disable animation in BrowseFragment when selected item change

I want to disable the default animation on items in a BrowseFragment when they are selected ie scaling animation and the change of position. I want the items to stay where they are and not change their size when selected.
So far I tried various things on my ListRowPresenter object like setting the OnItemViewSelectedListene to null but without successful effect.
How can I achieve this ? (I'm using the version 26 of the leanback library)
You can set the zoom factor for the animation to none by passing in ZOOM_FACTOR_NONE to the constructor of the ListRowPresenter.
There is a constructor for ListRowPresenter to control the animation (focusZoom).
From the documentation:
ListRowPresenter (int focusZoomFactor)
Constructs a ListRowPresenter with the given parameters.
Parameters
focusZoomFactor int: Controls the zoom factor used when an item view is focused. One of ZOOM_FACTOR_NONE, ZOOM_FACTOR_SMALL, ZOOM_FACTOR_XSMALL, ZOOM_FACTOR_MEDIUM, ZOOM_FACTOR_LARGE Dimming on focus defaults to disabled.
Example:
ArrayObjectAdapter adapter =
new ArrayObjectAdapter(new ListRowPresenter(ZOOM_FACTOR_NONE));
setAdapter(adapter);
ArrayObjectAdapter rowAdapter =
new ArrayObjectAdapter(new MyCardViewPresenter(getContext()));
HeaderItem header = new HeaderItem("Header Title");
ListRow row = new ListRow(header, rowAdapter);
for (Video video : videos) {
rowAdapter.add(video);
}
adapter.add(row);

Title in AppBar grows too large

On some views I show the name of a selected item as the title of the AppBar. But when the name is very long, the VBoxcontaining the title label grows to the prefWidth of the label. You can see the result on the first picture.
As a workaround I add a styleClass to the appBar, which sets the maxWidth for the label.
view.setOnShown(e -> getAppBar().getStyleClass().add("myStyleClass"));
Although it's working, it's bad practice to set the maxWidth like that, because it can't be adjusted to different screen sizes.
How can I achieve the result on the second picture, and make the title's width adapt to different screen sizes?
A quick and dirty workaround to set the max width of the label based on the scene dimensions could be, on a View subclass:
#Override
protected void updateAppBar(AppBar appBar) {
appBar.setTitleText("Very very very long title");
((Label) appBar.getTitle()).maxWidthProperty().bind(appBar.getScene().widthProperty().subtract(100));
}
where the amount to subtract will depend on the number of buttons (nav icon, action icons or menu button) you have in that view.

How can I reduce the amount of vertical space between lines of text using CSS?

The "obvious" answer is to use the line-height CSS rule, but this code (where I do use that):
private void GenerateSection7()
{
var headerFirstPart = new Label
{
CssClass = "finaff-webform-field-label",
Text = "<h2><strong>Section 7: Submit Information </strong></h2>"
};
headerFirstPart.Style.Add("display", "inline-block");
headerFirstPart.Style.Add("white-space", "pre");
headerFirstPart.Style.Add("line-height", "20%");
var headerSecondPart = new Label
{
CssClass = "finaff-webform-field-label",
Text = " (This payment is subject to post audit review by Financial Affairs)"
};
headerSecondPart.Style.Add("display", "inline-block");
headerFirstPart.Style.Add("line-height", "20%");
this.Controls.Add(headerFirstPart);
this.Controls.Add(headerSecondPart);
var submissionInstructions = new Label
{
CssClass = "finaff-webform-field-label",
Text = "<h4>Submit completed and approved form to Mail stop: FAST/AP Office</h4>"
};
this.Controls.Add(submissionInstructions);
}
...produces this result:
As you can see, the Cumberland gap could fit between these two lines. I started with 80% and kept reducing the percentage, but it makes no difference - 20% is no better than 50% (which was no better than 80%).
How can I cinch up the "play" between the lines?
UPDATE
Spurred on by oriol and quinnuendo, I changed my code to this:
private void GenerateSection7()
{
var headerFirstPart = new Label
{
CssClass = "finaff-webform-field-label",
Text = "<h2><strong>Section 7: Submit Information </strong></h2>"
};
headerFirstPart.Style.Add("display", "inline-block");
headerFirstPart.Style.Add("white-space", "pre");
//headerFirstPart.Style.Add("line-height", "20%");
headerFirstPart.Style.Add("margin", "0");
var headerSecondPart = new Label
{
CssClass = "finaff-webform-field-label",
Text = " (This payment is subject to post audit review by Financial Affairs)"
};
headerSecondPart.Style.Add("display", "inline-block");
//headerSecondPart.Style.Add("line-height", "20%");
headerFirstPart.Style.Add("margin", "0");
this.Controls.Add(headerFirstPart);
this.Controls.Add(headerSecondPart);
var submissionInstructions = new Label
{
CssClass = "finaff-webform-field-label",
Text = "<h4>Submit completed and approved form to Mail stop: FAST/AP Office</h4>"
};
submissionInstructions.Style.Add("margin", "0");
this.Controls.Add(submissionInstructions);
}
...but it still generates exactly the same page (with the Grand Canyon between the last two lines preventing Evel Kneivel from safely traversing the expanse).
Note: I tried both "0" (as shown above) and "0px" as the margin values, and the results are identical either way.
Line height is not the problem here. The problem is the space between the elements, which is controlled by the margin properties.
These tend to be preset to some values that allow for "normal" text flow, so you will have space before and after a heading and around paragraphs for instance.
Headings have various amounts of margin-top and margin-bottom depending on the level of the heading (h2 will have more than an h4). For instance it is "1em" sometimes (the width of a capital M in the current font).
So you will want to reduce these, or set them to 0 directly and experiment from there. The margins need to be set for the actual headings (h4, h2, or whatever) not for the containing element, they will not inherit it. For initial experiments you can try to just apply everything directly in the code, something like <h4 style='margin:0px'> ..... For a proper solution you would want to define actual CSS sheets for the particular case with introducing classes into the heading or in some surrounding div or an analogue.
In some cases you may also need to check out the padding property to fully control the spacings.
The problem is not the line-height but the vertical margins between elements. Also the fact that the headerSecondPart is untag.
See example for the solution.

Aligning and spacing of texts of buttons in a flextable using GAS

In a flextable I create rows with buttons in the first column showing the number of each row, and textboxes in other columns.
I would like to reduce space between rows to a minimum.
var btnField = app.createButton(numRow).setId(fieldId).setSize(20, 20)
.setStyleAttribute('marginBottom', 3).setStyleAttribute('marginTop', 0)
.setStyleAttribute('fontSize', 8).setText(numRow));
flextable.setCellSpacing(1).setCellPadding(1); //Minimum distance between rows ??
Problem regarding the buttons is that the texts are not in the middle of the buttons vertically. I cannot reduce the size of the buttons (using .setSize(20, 18) or so) as text will become outside the buttons at the bottom.
What styleattributes should I use to position the text of the buttons in the middle of the buttons vertically, right alligned with a small marginRight? The buttons itself should not exceed the size of the textboxes in order to minimize distances between rows.
If I have to use settings on the flextable, that will be OK as well of course.
Style attributes should be written using camelCase, use fontSize instead of fontsize and you'll get this :
which is nicely centered.
edit : I made a few tests on button text alignment and the results are a bit surprising ...
code and illustration below show that only horizontal alignment is doable on text content and that paddingTop applies but has side effects the other widgets as well
function doGet() {
var app = UiApp.createApplication().setTitle('test buttons');
var btn1 = app.createButton('test Button1').setPixelSize(200,60).setStyleAttributes({'fontFamily': 'serif','fontWeight': 'bold','fontSize':'14pt','text-align':'right'});
var btn2 = app.createButton('test Button2').setPixelSize(200,30).setStyleAttributes({'fontSize':'12pt','textAlign':'left'});
var btn3 = app.createButton('test Button3').setPixelSize(200,16).setStyleAttributes({'fontSize':'8pt','padding':'0px'});
var btn4 = app.createButton('test Button4').setPixelSize(200,60).setStyleAttributes({'fontSize':'8pt','paddingTop':'30px'});
app.add(btn1).add(btn2).add(btn3).add(btn4);
return app;
}
A combination od padding and verticalAlignment can give interesting results, see below :
var btn4 = app.createButton('testButton4').setPixelSize(200,60).setStyleAttributes({'fontSize':'8pt','paddingTop':'30px','vertical-align':'-11px'});

How do I Print a dynamically created Flex component/chart that is not being displayed on the screen?

I have a several chart components that I have created in Flex. Basically I have set up a special UI that allows the user to select which of these charts they want to print. When they press the print button each of the selected charts is created dynamically then added to a container. Then I send this container off to FlexPrintJob.
i.e.
private function prePrint():void
{
var printSelection:Box = new Box();
printSelection.percentHeight = 100;
printSelection.percentWidth = 100;
printSelection.visible = true;
if (this.chkMyChart1.selected)
{
var rptMyChart1:Chart1Panel = new Chart1Panel();
rptMyChart1.percentHeight = 100;
rptMyChart1.percentWidth = 100;
rptMyChart1.visible = true;
printSelection.addChild(rptMyChart1);
}
print(printSelection);
}
private function print(container:Box):void
{
var job:FlexPrintJob;
job = new FlexPrintJob();
if (job.start()) {
job.addObject(container, FlexPrintJobScaleType.MATCH_WIDTH);
job.send();
}
}
This code works fine if the chart is actually displayed somewhere on the page but adding it dynamically as shown above does not. The print dialog will appear but nothing happens when I press OK.
So I really have two questions:
Is it possible to print flex components/charts when they are not visible on the screen?
If so, how do I do it / what am I doing wrong?
UPDATE:
Well, at least one thing wrong is my use of the percentages in the width and height. Using percentages doesn't really make sense when the Box is not contained in another object. Changing the height and width to fixed values actually allows the printing to progress and solves my initial problem.
printSelection.height = 100;
printSelection.width = 100;
But a new problem arises in that instead of seeing my chart, I see a black box instead. I have previously resolved this issue by setting the background colour of the chart to #FFFFFF but this doesn't seem to be working this time.
UPDATE 2:
I have seen some examples on the adobe site that add the container to the application but don't include it in the layout. This looks like the way to go.
i.e.
printSelection.includeInLayout = false;
addChild(printSelection);
Your component has to be on the stage in order to draw its contents, so you should try something like this:
printSelection.visible = false;
application.addChild(printSelection);
printSelection.width = ..;
printSelection.height = ...;
...
then do the printing
i'm not completely sure, but in one of my application I have to print out a complete Tab Navigator and the only method i have found to print it is to automatically scroll the tabnavigator tab in order to show the component on screen when i add them to the printjob.
In this way they are all printed. Before i created the tabnaviagotr scrolling the print (to PDF) result was a file with all the pages of the tab but only the one visible on screen really printed.

Resources