Vaadin: TextArea scrolling doesn't work - textarea

I have something similar to this code:
TextArea textArea = new TextArea();
textArea.setSizeFull();
Panel dataPanel = new Panel("Panel", textArea);
dataPanel.setSizeFull();
textArea.setValue(... some very long text...);
The problem is that this TextArea appears without vertical scrollbar (and mouse-wheel scrolling also doesn't work), although inner text is longer than TextArea height (I can navigate lower using cursor and keyboard down arrow).
How do I enable scrolling in this component?

A bit weird, but as per the documentation if you disable word-wrapping in a text-area, you'll get the vertical scroll-bar:
Word Wrap
The setWordwrap() sets whether long lines are wrapped ( true - default) when the line length reaches the width of the writing area. If the word wrap is disabled (false), a vertical scrollbar will appear instead. The word wrap is only a visual feature and wrapping a long line does not insert line break characters in the field value; shortening a wrapped line will undo the wrapping.
The following code sample illustrates this behaviour with Vaadin 8.0.6. Please note my class extends Panel to match your sample but at this point you can eliminate it:
public class PanelWithScrollableTextField extends Panel {
public PanelWithScrollableTextField() {
TextArea textArea = new TextArea();
textArea.setWordWrap(false);
textArea.setSizeFull();
setContent(textArea);
setSizeFull();
StringBuffer buffer = new StringBuffer();
IntStream.range(1, 100).forEach(value -> buffer.append(value).append("\r\n"));
textArea.setValue(buffer.toString());
}
}
Result:
P.S. I know it's a bit weird to grasp, but panels are used to scroll surfaces that are larger then the panel size, so if we'd get it working, you'd be scrolling the text area itself, not its content. You can see below a sample to better understand what I mean:
public class PanelWithScrollableTextField extends Panel {
public PanelWithScrollableTextField() {
TextArea textArea = new TextArea();
textArea.setWordWrap(false);
textArea.setHeight("500px"); // fixed size with height larger than the panel
setContent(textArea);
setHeight("100px"); // fixed height smaller than the content so we get a scroll bar
StringBuffer buffer = new StringBuffer();
IntStream.range(1, 100).forEach(value -> buffer.append(value).append("\r\n"));
textArea.setValue(buffer.toString());
}
}
Result:

You can change it CSS also like below .
.v-textarea { overflow-y: auto ! important;}

Related

How to make text in vaadin Grid cell to wrap

I need to make Vaadin 8 Grid cell text wrap. I tried to follow this link in Vaadin Forum.
https://vaadin.com/forum/thread/16908210/vaadin-8-grid-wrap-long-lines
My Grid contains Strings only in every cell.
I have a StyleGenerator class like this:
public class MyGridStyleGenerator<ArrayList> implements StyleGenerator {
public String apply(Object item) {
return ".m-grid-cell-wrapper";
}
}
I am converting from Vaadin 6 so I still use old theme ("../reindeer/legacy-styles.css")
In my styles.css file, there is:
.m-grid-cell-wrapper {
word-wrap: break-word;
white-space: normal;
}
In the class that creates the Grid, I have:
Grid<List<String>> table = new Grid<>("My Test Grid");
//skip setting items code since the cell content shows up fine.
MyGridStyleGenerator style = new MyGridStyleGenerator();
table.setStyleGenerator(style);
table.setBodyRowHeight(35); // more than two lines of text height
I set each column width to a fixed value using setWidth() of Grid.Column so that more columns can be displayed in the given window.
The problem is that when the Grid is displayed, text longer than column width does not wrap.
What did I miss?
Thanks for any advice.
BTW, there is another question on this topic in Stack Overflow where the answer is to use label.setStyleName(ValoTheme.LAYOUT_HORIZONTAL_WRAPPING);
I don't have Label and don't use Valo style.
The CSS class controlling the Grid cell is .v-grid-cell, so I added the following in my styles.css file.
.v-grid-cell {
white-space: normal; }
This caused the text in Grid cell to wrap.

Horizontally centering a popup window in Vaadin

I have added a popup window to my main UI as follows:
Window component = new Window();
UI.getCurrent().addWindow(component);
Now, I want my popup to be centered horizontally and e.g. 40 pixels from the top of the screen. As far as I can see Vaadin has 4 methods for positioning my window.
component.center()
component.setPosition(x, y)
component.setPositionX(x)
component.setPositionY(y)
None of these are really what I want. I was hoping at first that setPositionY might help me. This does allow me to get the right distance from the top, but the x-position is now set to 0, where I wanted it to be centered.
The setPosition might have helped if I was able to calculate what the x-position should be, but this would require me to know the width of the component in pixels, but component.getWidth just tells me 100%.
Next I tried to use CSS styling on the component, writing and explicit css rule and adding it to the component with addStyleName. It seems though that Vaadin overrides whatever I wrote in my css with its own defaults...
Any ideas how to get my Window component positioned correctly?
I used the methods getBrowserWindowWidth() and getBrowserWindowHeight() from the com.vaadin.server.Page class for this.
I centered my "log" window horizontally in the lower part of the browser window with
myWindow.setHeight("30%");
myWindow.setWidth("96%");
myWindow.setPosition(
(int) (Page.getCurrent().getBrowserWindowWidth() * 0.02),
(int) (Page.getCurrent().getBrowserWindowHeight() * 0.65)
);
Solution 1: Use SizeReporter
Indeed, setPositionY() will reset the window's centered property to false. As the width of your pop-up and that of your browser window are not know before they appear on the screen, the only way I know to get those values is to use the SizeReporter add-on. Its use is quite straightforward:
public class MyUI extends UI {
private Window popUp;
private SizeReporter popUpSizeReporter;
private SizeReporter windowSizeReporter;
#Override
protected void init(VaadinRequest request) {
Button button = new Button("Content button");
VerticalLayout layout = new VerticalLayout(button);
layout.setMargin(true);
popUp = new Window("Pop-up", layout);
popUp.setPositionY(40);
addWindow(popUp);
popUpSizeReporter = new SizeReporter(popUp);
popUpSizeReporter.addResizeListenerOnce(this::centerPopUp);
windowSizeReporter = new SizeReporter(this);
windowSizeReporter.addResizeListenerOnce(this::centerPopUp);
}
private void centerPopUp(ComponentResizeEvent event) {
int popUpWidth = popUpSizeReporter.getWidth();
int windowWidth = windowSizeReporter.getWidth();
if (popUpWidth == -1 || windowWidth == -1) {
return;
}
popUp.setPositionX((windowWidth - popUpWidth) / 2);
}
}
This piece of code will be okay as long as you don't resize the pop-up. If you do, it will not be automatically recentered. If you replace addResizeListenerOnce() by addResizeListener() then it will automatically recenter the pop-up but you'll get some "UI glitches" as the add-on sends resize events almost continually while you're resizing your pop-up...
You could try to do it using CSS, but I personally avoid CSS as much as I can with Vaadin :).
You'll need to recompile the widgetset after you've added the add-on as a dependency.
Solution 2: Use com.vaadin.ui.JavaScript
I won't vouch for the portability of this solution but I guess it will work on most modern browsers.
public class MyUI extends UI {
private Window popUp;
#Override
protected void init(VaadinRequest request) {
Button button = new Button("Content button");
VerticalLayout layout = new VerticalLayout(button);
layout.setMargin(true);
popUp = new Window("Pop-up", layout);
popUp.setPositionY(40);
popUp.addStyleName("window-center");
addWindow(popUp);
// Add a JS function that can be called from the client.
JavaScript.getCurrent().addFunction("centerWindow", args -> {
popUp.setPositionX((int) ((args.getNumber(1) - args.getNumber(0)) / 2));
});
// Execute the function now. In real code you might want to execute the function just after the window is displayed, probably in your enter() method.
JavaScript.getCurrent().execute("centerWindow(document.getElementsByClassName('window-center')[0].offsetWidth, window.innerWidth)");
}
}

Vaadin: How do make a button align to the top right of my page?

I need to align a button to the right of my page in a vertical layout.
Please tell me method to do this.
private Button createBackButton() {
Button bButton = new Button("Back");
bButton.setIcon(FontAwesome.ARROW_LEFT);
bButton.addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
doSomething();
}
});
return bButton;
}
Null,
In order to align your button to the top-right of your VerticalLayout, use VerticalLayout's setComponentAlignment() method. Also note that the VerticalLayout itself needs to be big enough so that the button can even have some space to move around in there so it looks like it's being aligned to the top-right. By default the VerticalLayout will just get as big as the components inside it. You need to give it a bigger size using setWidth() and setHeight(), or make it take up the whole space as its parent component/layout using setSizeFull() (note that the parent layout, if any, also needs to be big enough so it has space inside it too).
So the code would look like:
VerticalLayout vl = new VerticalLayout();
vl.setSizeFull();
Button backButton = createBackButton();
vl.addComponent(backButton);
vl.setComponentAlignment(backButton,Alignment.TOP_RIGHT);
Hope that helps.

Vaadin label gets hidden if other layout component is set to expand

If I use following code to create a UI using Vaadin,
#Override
protected void init(VaadinRequest request) {
HorizontalLayout horizontalLayout = new HorizontalLayout();
horizontalLayout.addComponent(new Label("Why am I not shown?"));
Button button = new Button("expanding button");
horizontalLayout.addComponent(button);
horizontalLayout.setExpandRatio(button, 1);
horizontalLayout.setWidth(100, Unit.PERCENTAGE);
setContent(horizontalLayout);
}
The label I added to horizontalLayout is not shown in the created UI. Why is that? What I expect to happen in this case is the label to take its required width and the button to take the rest of the width. But the label is not shown at all.
Please don't ask me why I want to expand the button. This is just a MCVE and my real UI is somewhat more complex.
The Button has undefined size by default. So space will be shared by the 100% sized Label (by default) with expand ratio of 0 and the excess space of the Button cell with expand ratio 1. So all space is given to the excess space of the button.
Set the Label to have a undefined size with label.setSizeUndefined() and will work as you expect.
Note that relative sized components can lost all his space when using a expand ratio.
For example:
HorizontalLayout horizontalLayout = new HorizontalLayout();
Label l1 = new Label("one");
Label l2 = new Label("two");
Label l3 = new Label("three");
horizontalLayout.addComponent(l1);
horizontalLayout.addComponent(l2);
horizontalLayout.addComponent(l3);
horizontalLayout.setExpandRatio(l2, 1);
Will show only label "two".

Preventing flexcroll on event

What I have currently is a very simple div that has a flexcroll scroll bar. This simple div contains some draggable itmes inside of it. My goal is to be able to drag one of the items and and move it about without the flexcroll scroll bar moving.
As it stands right now if I were to drag one of the items below the viewable area the simple div will scroll down. I would like to prevent this.
I'm using jQuery UI for the draggable items. I've already tried using the option "scroll:false" but this does not work for flexcroll.
I'm sorry I don't have any example code, I'm currently away from my work computer.
flexcroll: http://www.hesido.com/web.php?page=customscrollbar
I don't know if you have already resolved this problem. This morning, I have the same problem and I found your post. After that, I have googled a lot to find a solution without any lucky. So finally, I decided to do someting myself, I hope my idea will help you.
After read the Programming Guid, I found that in this version (2.0) of flexcroll, we could register a function for onfleXcroll whose description could be found by searching the keyword "Pseudo-event: onfleXcroll". This is to say that the method will be executed after a scroll is done. So here, what I restore the "top" style with the value before you drag an element.
Here are the code
var $assetswrapper; // This variable indicates the contentwrapper of you div.
var $assetsscrollbar; // This variable indicates the vscroller of you div.
window.onfleXcrollRun = function () { // This method will be executed as soon as the div has been rendered with the help of flexcroll
// You could find these two divs by using firebug, because the top value of these two divs will be changed when we scroll the div which use the class .flexcroll.
$assetswrapper = $('#contentwrapper');
$assetsscrollbar = $('#vscrollerbar');
}
var wrapperTopPosition = 0; // This is used to stock the top value of the wrapperContent before dragging.
var scrollbarTopPosition = 0; // This is used to stock the top value of the scrollbar before dragging.
var dragged; // This is a boolean variable which is used for indicating whether the draggable element has been dragged.
var dropped = false; // This is a boolean variable which used to say whether the draggable element has been dropped.
$('.draggable').draggable({ // you could change .draggable with any element.
start: function (event, ui) {
// Your code here.
wrapperTopPosition = $assetswrapper.position().top;
scrollbarTopPosition = $assetsscrollbar.position().top
dragged = true;
},
stop: function (event, ui) {
// Your code here.
dragged = false;
dropped = true;
}
});
$('your drag div')[0].onfleXcroll = function () { // This method will be called each time when a scroll has been done.
if (dragged) {
$assetswrapper.css('top', wrapperTopPosition);
$assetsscrollbar.css('top', scrollbarTopPosition);
} else {
// Code here is used for keeping the top position as before even though you have dragged an element out of this div for a long time.
// You could test the scrollbar without this piece of code, if you drag an element out of the div for a long time, the scrollbar will keep its position,
// but after you dropped this element and try to scroll the div, then the scrollbar will reach the end of the div. To solve this problem,
// I have introduced the method setScrollPos with the old top position plus 72. 72 here is to set the scroll increment for this scroll, I know
// this value is not fit for any size of windows, but I don't know how to get the scroll-increment automatically.
if (dropped) {
dropped = false;
$('your drag div')[0].fleXcroll.setScrollPos(false, Math.abs(wrapperTopPosition) + 72);
$('your drag div')[0].fleXcroll.setScrollPos(false, Math.abs(wrapperTopPosition) + 72);
}
}
};
I hope this could give you a help if you haven't found any solution yet.

Resources