Vaadin Tabsheet undesired refreshing of tab content - java

I have a Vaadin-TabSheet which has a BrowserFrame in each tab. I notice the following undesired behavior: When I change the tab by clicking on it, the browserframe reloads, possibly erasing any inputs the user might have made in that tab.
How can I keep the tab from reloading? Is there an alternative to the tabSheet?

I now have built my own TabSheet.
I tried to use setVisible on the tab contents, but this also made the browser frame reload. So i came up with the following code to change the size of contents:
private final HorizontalLayout buttons;
private final GridLayout contents;
/**
* Construct a new MyTabSheet
*/
public MyTabSheet() {
buttons = new HorizontalLayout();
contents = new GridLayout();
....
if(t.isSelected()) {
selectedComponent = t.getComponent();
} else {
t.getComponent().setSizeUndefined();
t.getComponent().setWidth(0.0f, Unit.PIXELS);
t.getComponent().setHeight(0.0f, Unit.PIXELS);
}
}
if(null != selectedComponent) {
String frameHeight;
if(selectedComponent instanceof BrowserFrame) {
BrowserFrame bf = (BrowserFrame)selectedComponent;
frameHeight = (String) bf.getData();
} else {
frameHeight = "800px";
}
selectedComponent.setSizeFull();
selectedComponent.setHeight(frameHeight);
}

Related

Make status trimbar contribution grow when its content changes

I'm trying to add an Eclipse status trimbar contribution where the contents of the contribution (i.e., child elements' text) dynamically change. Note that I'm not trying to add "line, column" information into the status bar.
Ideally, the contribution's width should adapt to the width of its contents, a bit like what happens in VSCode:
However, if that isn't easily feasible, an acceptable alternative would be to have a "fixed" width for the status trimbar, or even a fixed width for each individual child (since I don't intend to have children appearing and disappearing).
Below is what I've tried. How do you think I should do this if nothing I've tried for the past 2 days worked?
In case you think the problem might actually be an Eclipse bug, note that I'm using Eclipse version 2021-06 (4.20.0) on Linux.
What I have tried
I have this in plugin.xml:
<extension
point="org.eclipse.ui.menus">
<menuContribution
locationURI="toolbar:org.eclipse.ui.trim.status">
<toolbar
id="some.package.StatusTrimBarContribution">
<control
class="some.package.StatusTrimBarContribution">
</control>
</toolbar>
</menuContribution>
</extension>
I've tried doing this in at least 4 different ways. As a reference, here is the class StatusTrimBarContribution:
public class StatusTrimBarContribution extends WorkbenchWindowControlContribution {
// A
private static String currText = /* see below */;
private Label m_lbl = null;
private Label m_lbl2 = null;
private Control m_root = null;
public StatusTrimBarContribution() {
// Register to String event
}
#Override
public void dispose() {
// Unregister from String event
}
#Override
protected Control createControl(Composite parent) {
// B
}
#Subscribe // From guava
private void someEventHandler(String event) {
currText = "lp_much_longer";
if (m_lbl != null) {
m_lbl.setText();
m_root.getParent().requestLayout();
}
}
}
Attempt #1
In this attempt we add an intermediary Composite between the labels and parent, we use a GridLayout on the intermediary, and we add a GridData into m_lbl.
// A
private static String currText = "empty";
// B
#Override
protected Control createControl(Composite parent) {
GridLayout gl = new GridLayout(2, false);
Composite comp = new Composite(parent, SWT.NONE);
comp.setLayout(gl);
m_lbl = new Label(comp, SWT.RIGHT);
m_lbl.setText(currText);
GridDataFactory.defaultsFor(m_lbl).hint(200, SWT.DEFAULT).applyTo(m_lbl);
m_lbl2 = new Label(comp, SWT.RIGHT);
m_lbl2.setText("lbl2");
m_root = comp;
return comp;
}
The result is that the labels are too tall and get truncated. Note that I've also tried setting the margin height to 0, and, while it's better than below, the labels would still get truncated.
Attempt #2
Compared to #1, we remove the intermediary Composite, and instead use the layout directly on parent. Also, we remove the GridData, because, at this point, why not.
// A
private static String currText = "empty";
// B
#Override
protected Control createControl(Composite parent) {
GridLayout gl = new GridLayout(2, false);
parent.setLayout(gl);
m_lbl = new Label(parent, SWT.RIGHT);
m_lbl.setText(currText);
m_lbl2 = new Label(parent, SWT.RIGHT);
m_lbl2.setText("lbl2");
m_root = m_lbl;
return m_lbl;
}
The result is the same as before, except, additionally, that m_lbl is not large enough to hold the text:
Attempt #3
Compared to #2, we additionally remove the layout.
// A
private static String currText = "empty";
// B
#Override
protected Control createControl(Composite parent) {
m_lbl = new Label(parent, SWT.RIGHT);
m_lbl.setText(currText);
m_lbl2 = new Label(parent, SWT.RIGHT);
m_lbl2.setText("lbl2");
m_root = m_lbl;
return m_lbl;
}
The labels are no longer too tall, however, the width of the labels is still to small for the text:
Attempt #4
Compared to #3, we initially assign a very long string into m_lbl.
// A
// Yes, this is ridiculous
private static String currText = " ".repeat(60);
// B
#Override
protected Control createControl(Composite parent) {
m_lbl = new Label(parent, SWT.RIGHT);
m_lbl.setText(currText);
m_lbl2 = new Label(parent, SWT.RIGHT);
m_lbl2.setText("lbl2");
m_root = m_lbl;
return m_lbl;
}
The result is that both labels are completely visible, but now m_lbl2 has the same width as m_lbl, which is far more than I want. Plus, if the user's font is different from mine, the width of the labels might become too large or too small due to the initial string.
Using the minimum width setting of GridData works for me:
#Override
protected Control createControl(final Composite parent)
{
final Composite comp = new Composite(parent, SWT.NONE);
GridLayoutFactory.fillDefaults().numColumns(2).applyTo(comp);
m_lbl = new Label(comp, SWT.RIGHT);
m_lbl.setText("label 1");
GridDataFactory.fillDefaults().grab(true, false).minSize(200, SWT.DEFAULT).applyTo(m_lbl);
m_lbl2 = new Label(comp, SWT.RIGHT);
m_lbl2.setText("lbl2");
GridDataFactory.fillDefaults().grab(true, false).minSize(100, SWT.DEFAULT).applyTo(m_lbl2);
m_root = comp;
return comp;
}
Note: Changing the layout of parent is against the rules, it could damage the layout of other components.

Vaadin - Responsive Columns

I'm new to using Vaadin and have been trying to work out how I can make 2 Components be side by side when at full screen, but then stack on top of each other when the screen is mobile.
My current understanding is that a HorizontalLayout puts things side by side. And a VerticalLayout puts things on top of one another. So how do I go about using the functionality from both?
You need to look into using a different Layout type. Vaadin offers you a CssLayout and CustomLayout as well as the standard Vertical and Horizontal.
My personal favourite at the moment is using a CssLayout and then using a custom CSS Grid to make the components responsive.
Java:
#StyleSheet("MyStyleSheet.css")
public class ResponsiveLayout extends CssLayout {
private static final long serialVersionUID = -1028520275448675976L;
private static final String RESPONSIVE_LAYOUT = "responsive-layout";
private static final String LABEL_ONE = "label-one";
private static final String LABEL_TWO = "label-two";
private Label labelOne = new Label();
private Label labelTwo = new Label();
public ResponsiveLayout() {
config();
addComponents(labelOne, labelTwo);
}
private void config() {
addStyleName(RESPONSIVE_LAYOUT);
labelOne.addStyleName(LABEL_ONE);
labelTwo.addStyleName(LABEL_TWO);
}
}
CSS:
.responsive-layout {
display: grid !important;
grid-template-rows: auto;
grid-template-columns: 1fr 1fr;
display: -ms-grid !important; /* IE */
-ms-grid-rows: auto; /* IE */
-ms-grid-columns: 1fr 1fr; /* IE */
}
.label-one {
grid-column: 1;
-ms-grid-column: 1; /* IE */
}
.label-two {
grid-column: 2;
-ms-grid-column: 2; /* IE */
}
#media all and (max-width : 992px) {
.responsive-layout {
grid-template-columns: 1fr;
-ms-grid-columns: 1fr; /* IE */
}
.label-one {
grid-column: 1;
-ms-grid-column: 1; /* IE */
}
.label-two {
grid-column: 1;
-ms-grid-column: 1; /* IE */
}
}
You can use a Vaadin Add-on responsive layout. Using the grid system of flexboxgrid
#Override
public void enter(ViewChangeListener.ViewChangeEvent event) {
ResponsiveLayout responsiveLayout = new ResponsiveLayout();
responsiveLayout.setSizeFull();
ResponsiveRow rowOne = responsiveLayout.addRow();
Button deleteButton = new Button("", VaadinIcons.TRASH);
deleteButton.addStyleName(ValoTheme.BUTTON_DANGER);
deleteButton.setSizeFull();
Button commentButton = new Button("",VaadinIcons.COMMENT);
commentButton.addStyleName(ValoTheme.BUTTON_PRIMARY);
commentButton.setSizeFull();
Button editButton = new Button("", VaadinIcons.EDIT);
editButton.addStyleName(ValoTheme.BUTTON_FRIENDLY);
editButton.setSizeFull();
rowOne.addColumn().withDisplayRules(12,6,4,4).withComponent(deleteButton);
rowOne.addColumn().withDisplayRules(12,6,4,4).withComponent(commentButton);
rowOne.addColumn().withDisplayRules(12,6,4,4).withComponent(editButton);
ResponsiveRow rowTwo = responsiveLayout.addRow();
Label labelOne = new Label("LABEL 1");
Label labelTwo = new Label("LABEL 2");
rowTwo.addColumn().withDisplayRules(12,6,4,4).withComponent(labelOne);
rowTwo.addColumn().withDisplayRules(12,6,4,4).withComponent(labelTwo);
setSizeFull();
addComponent(responsiveLayout);
}
You can view a basic example here
You can combine your layouts, you might want to put two horizontal layouts within a vertical layout. Think of "boxes within boxes". From there you can fine-tune your layout via css, just analyse the generated HTML.
They had a webinar about layouts some time ago, maybe that helps.

Vaadin problems with UI size and scrollbar

I'm realitively new to vaadin and I'm struggling with this problems for 2 days now and I'm desperate.
I modified the original addressbook example and it was perfect until that point when I had to expand the ContactForm with another controlls.
It's easier to show what i want to achieve.
It would be good if I could scroll on the right, but I cant. I show what i have already maybe some of you will notice my fault. I wont post all of the code, just the necessary parts.
This is where I create the main layout.
public class VaadinKoliUI extends UI {
#Override
protected void init(VaadinRequest request) {
TabSheet tabsheet = new TabSheet();
HorizontalLayout residentalsTab = new ResidentalsUI();
residentalsTab.setSizeFull();
tabsheet.addTab(residentalsTab,"Lakók");
tabsheet.setSizeFull();
setContent(tabsheet);
}
}
public class ResidentalsUI extends HorizontalLayout implements View{
private Grid residentalsList = new Grid();
ResidentalFormTest residentalForm = new ResidentalFormTest(this);
public ResidentalsUI(){
buildLayout();
}
private void buildLayout(){
HorizontalLayout actions = new HorizontalLayout(filter,excelDownload, newResidental);
actions.setWidth("100%");
filter.setWidth("100%");
actions.setExpandRatio(filter, 1);
VerticalLayout left = new VerticalLayout(actions, getResidentalsList());
left.setSizeFull();
getResidentalsList().setSizeFull();
left.setExpandRatio(getResidentalsList(), 1);
HorizontalLayout mainLayout = new HorizontalLayout(left, residentalForm);
mainLayout.setSizeFull();
mainLayout.setExpandRatio(left, 1);
this.setSizeFull();
this.addComponent(mainLayout);
}
}
public class ResidentalFormTest extends Panel{
FormLayout content = new FormLayout();
Button save = new Button("Save", this::save);
//more buttons and controlls
public ResidentalFormTest(ResidentalsUI rUI) {
this.rUI = rUI;
buildLayout();
}
private void buildLayout() {
this.setSizeUndefined();
content.setMargin(true);
HorizontalLayout actions = new HorizontalLayout(save, cancel);
actions.setSpacing(true);
content.addComponents(actions, name, sex, address, email, phoneNumber, major,classYear,neptunCode,
roomNumber, rfidCode,comment,equipment,equipment1,equipment2);
actions.setSizeUndefined();
this.setContent(content);
}
}
So from what I understood yet, I have to use a Panel because the FormLayout is not capable to show a scrollbar. I should set my root to full with .setSizeFull() and the childs to undefined with .setSizeUndefined() so it would be the size of the browser window and if something is bigger it would show a scrollbar.
If I modify the VaadinKoliUI class as the following I have the scrollbar but the ui shrinks.
public class VaadinKoliUI extends UI {
#Override
protected void init(VaadinRequest request) {
TabSheet tabsheet = new TabSheet();
HorizontalLayout residentalsTab = new ResidentalsUI();
residentalsTab.setSizeUndefined();
tabsheet.addTab(residentalsTab,"Lakók");
tabsheet.setSizeFull();
setContent(tabsheet);
}
}
Like this:
And now I don't know what to do.
But if someone has an easier and quicker idea, to make the ContactForm to scrollable please tell me.
Thanks in advance
Balázs
I should set my root to full with .setSizeFull() and the childs to undefined...
In your case you should see the root as being your Panel and the FormLayout as the child. As per the Vaadin book:
Normally, if a panel has undefined size in a direction, as it has by
default vertically, it will fit the size of the content and grow as
the content grows. However, if it has a fixed or percentual size and
its content becomes too big to fit in the content area, a scroll bar
will appear for the particular direction
The image below is a naive attempt at a visual representation:
This being said, from the moment you modified ResidentalFormTest to extend a Panel and set the FormLayout as it's content, in order to make your panel have a scroll:
set the panel size to 100%, in ResidentalFormTest.buildLayout():
this.setSizeFull()
set the content size to undefined so it can "expand" beyond the panel size: in ResidentalFormTest.buildLayout(): content.setSizeUndefined()
To fix the space allocation between the grid and panel I reckon a 3:1 ratio should suffice. in ResidentalsUI.buildLayout():
mainLayout.setExpandRatio(left, 3);
mainLayout.setExpandRatio(residentalForm, 1);
NOTE: At times it may come in handy to inspect (or experiment with changes) the rendered elements' properties, styles, etc. Some browsers (chrome, firefox) have built-in support for such developer tools, accessible through a menu or a keyboard combination such as CTRL+SHIFT+I
I think you should have
VaadinKoliUI.setSizeFull
ResidentalsUI.setSizeFull
ResidentalsUI.residentalsList.setSizeFull
ResidentalFormTest.setSizeFull
ResidentalFormTest.content.setSizeUndefined
ResidentalsUI.left.setSizeFull
I also suggest to eliminate the HorizontalLayout mainLayout in ResidentalsUI since it is a horizontal layout itself (and if possible to rename it since it isn't a UI and remove the implements View since it does not seem a view).
Your expand ratios looks good, here are the classes I would wrote:
public class VaadinKoliUI extends UI {
#Override
protected void init(VaadinRequest request) {
TabSheet tabsheet = new TabSheet();
ResidentalsLayout residentalsTab = new ResidentalsLayout();
residentalsTab.setSizeFull();
tabsheet.addTab(residentalsTab,"Lakók");
tabsheet.setSizeFull();
setContent(tabsheet);
}
public class ResidentalsLayout extends HorizontalLayout {
private Grid residentalsList = new Grid();
ResidentalFormTest residentalForm = new ResidentalFormTest(this);
public ResidentalsLayout(){
buildLayout();
}
private void buildLayout(){
HorizontalLayout actions = new HorizontalLayout(filter,excelDownload, newResidental);
actions.setWidth("100%");
filter.setWidth("100%");
actions.setExpandRatio(filter, 1);
VerticalLayout left = new VerticalLayout(actions, getResidentalsList());
left.setSizeFull();
residentalsList.setSizeFull();
left.setExpandRatio(residentalsList , 1);
addComponents(left, residentalForm);
setExpandRatio(left, 1);
setSizeFull();
}
}
public class ResidentalFormTest extends Panel {
FormLayout content = new FormLayout();
Button save = new Button("Save", this::save);
//more buttons and controlls
public ResidentalFormTest(ResidentalsLayout rUI) {
this.rUI = rUI;
buildLayout();
}
private void buildLayout() {
setSizeFull();
content.setMargin(true);
HorizontalLayout actions = new HorizontalLayout(save, cancel);
actions.setSpacing(true);
content.addComponents(actions, name, sex, address, email, phoneNumber, major,classYear,neptunCode, roomNumber, rfidCode, comment, equipment, equipment1, equipment2);
content.setSizeUndefined();
setContent(content);
}
}
Let me know if it works as expected.

Java Swing countrycombobox with icons

I hope someone can help me out. Iam trying to create a "countrycombobox" with icons in Java Swing. I found some stuff, but nothing did work for me. Maybe the problem is, that Iam still "new" to Java.
I just want it simple like this: http://www.zomex.com/libs/images/layout/whmcs-template-language-select-w-flags-eco.jpg
Just the flags in front of the countrys.
I would really appreciate a working example. I really wonder, that there is no standard option or a good code snippet(used Google a lot to find help here) for stuff like this.
I found a better example and wanna share my stuff with you. There is just one problem left, that I dont get it sized.
package view;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CountryComboBox extends JPanel {
ImageIcon[] images;
String[] imgStrings = {"de"};
/*
* Despite its use of EmptyBorder, this panel makes a fine content
* pane because the empty border just increases the panel's size
* and is "painted" on top of the panel's normal background. In
* other words, the JPanel fills its entire background if it's
* opaque (which it is by default); adding a border doesn't change
* that.
*/
public CountryComboBox() {
super(new BorderLayout());
//Load the images and create an array of indexes.
images = new ImageIcon[imgStrings.length];
Integer[] intArray = new Integer[imgStrings.length];
for (int i = 0; i < imgStrings.length; i++) {
intArray[i] = new Integer(i);
images[i] = createImageIcon("/res/" + imgStrings[i] + ".png");
if (images[i] != null) {
images[i].setDescription(imgStrings[i]);
}
}
//Create the combo box.
JComboBox imgList = new JComboBox(intArray);
ComboBoxRenderer renderer= new ComboBoxRenderer();
imgList.setRenderer(renderer);
imgList.setMaximumRowCount(3);
//Lay out the demo.
add(imgList, BorderLayout.PAGE_START);
//setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
}
/** Returns an ImageIcon, or null if the path was invalid. */
protected static ImageIcon createImageIcon(String path) {
java.net.URL imgURL = CountryComboBox.class.getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
class ComboBoxRenderer extends JLabel
implements ListCellRenderer {
private Font uhOhFont;
public ComboBoxRenderer() {
setOpaque(true);
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);
}
/*
* This method finds the image and text corresponding
* to the selected value and returns the label, set up
* to display the text and image.
*/
#Override
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
//Get the selected index. (The index param isn't
//always valid, so just use the value.)
int selectedIndex = ((Integer)value).intValue();
if (isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
//Set the icon and text. If icon was null, say so.
ImageIcon icon = images[selectedIndex];
String img = imgStrings[selectedIndex];
setIcon(icon);
if (icon != null) {
setText(img);
setFont(list.getFont());
} else {
setUhOhText(img + " (no image available)",
list.getFont());
}
return this;
}
//Set the font and text when no image was found.
protected void setUhOhText(String uhOhText, Font normalFont) {
if (uhOhFont == null) { //lazily create this font
uhOhFont = normalFont.deriveFont(Font.ITALIC);
}
setFont(uhOhFont);
setText(uhOhText);
}
}
}
I call it in a JPanel with absolute layout:
JComponent newContentPane = new CountryComboBox();
newContentPane.setOpaque(true); //content panes must be opaque
newContentPane.setBounds(10, 75, 50, 26);
contentPane.add(newContentPane);
setBounds isnt working, just to get the right position. I cant size it with this.
Best regards
Acanis

expand and collapse icons

As you can see from the images below the expand and collapse icons are gray, as is the row selection highlight. This causes you to not see the expand or collapse icon (Note: Not the folder icon) when the row is highlighted, I want to have a white expand or collapse icon for the row that is selected. How can that be done?
Something else that would also be cool is, to have the expand and collapse icons completely hidden until the JTree gains focus. like windows 7's tree.
Google says -according to this post: http://www.exampledepot.com/egs/javax.swing.tree/DefIcons.html - :
// Retrieve the three icons
Icon leafIcon = new ImageIcon("leaf.gif");
Icon openIcon = new ImageIcon("open.gif");
Icon closedIcon = new ImageIcon("closed.gif");
// Create tree
JTree tree = new JTree();
// Update only one tree instance
DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer)tree.getCellRenderer();
renderer.setLeafIcon(leafIcon);
renderer.setClosedIcon(closedIcon);
renderer.setOpenIcon(openIcon);
// Remove the icons
renderer.setLeafIcon(null);
renderer.setClosedIcon(null);
renderer.setOpenIcon(null);
// Change defaults so that all new tree components will have new icons
UIManager.put("Tree.leafIcon", leafIcon);
UIManager.put("Tree.openIcon", openIcon);
UIManager.put("Tree.closedIcon", closedIcon);
// Create tree with new icons
tree = new JTree();
// Update row height based on new icons;
Certainly, I'm not sure if you can modify only the color of the images on-the-go. But you can always create new icons, right?
You can try this. You should note however to get this to work, I had to override setUI on the tree to only allow my TreeUI.
private class IconTreeUI extends BasicTreeUI {
private Icon collapseIcon = null;
private Icon expandIcon = null;
#Override
public Icon getCollapsedIcon() {
if (collapseIcon == null) {
collapseIcon = new ImageIcon(yourCollapseImageHere);
}
return collapseIcon;
}
#Override
public Icon getExpandedIcon() {
if (expandIcon == null) {
expandIcon = new ImageIcon(yourExpandImageHere);
}
return expandIcon;
}}

Categories