Can replace Vaadin layout component inside Panel? - vaadin

Am using Vaadin 7.3.10.
I have added a layout component inside a panel in order that
the layouts shall be scrolled if required.
However when I try to replace the layout component, the new
component adds to (is shown below) rather than replaces the
existing component - see below for code sample.
How/Can this be done?
n.b. if the layout is not contained inside the panel, the
replacement occurs correctly.
Also, I do not require to use the Navigator for this.
Thank you,
Steve...
import com.vaadin.ui.Button;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Button.ClickEvent;
public class NewComponent extends VerticalLayout {
private VerticalLayout mainLayout = new VerticalLayout();
private Panel panel = new Panel();
public NewComponent() {
mainLayout.addComponent(new Label("Main"));
mainLayout.setSizeFull();
addComponent(mainLayout);
panel.setWidth("1000px");
panel.setHeight("500px");
panel.setContent(mainLayout);
Button button = new Button("Click Me");
button.addClickListener(new Button.ClickListener() {
public void buttonClick(ClickEvent event) {
replaceComponent(mainLayout, new Label("what's wrong?"));
}
});
mainLayout.addComponent(button);
addComponent(panel);
}
}
public class TestUI extends UI {
#WebServlet(value = "/*", asyncSupported = true)
#VaadinServletConfiguration(productionMode = false, ui = TestUI.class)
public static class Servlet extends VaadinServlet {
}
#Override
protected void init(VaadinRequest request) {
setContent(new NewComponent());
}

You have to call replaceComponent on the mainLayout and not with.
right now it looks like this:
<newComponent>
<panel>
<mainLayout>
<labelMain/>
<clickMeButton/>
</mainLayout>
</panel>
</newComponent>
then you call replaceComponent on newComponent, which will add the label like this
<newComponent>
<panel>
<mainLayout>
<labelMain/>
<clickMeButton/>
</mainLayout>
</panel>
<whatsWrongLabel/>
</newComponent>
It should look like this:
<newComponent>
<panel>
<mainLayout>
<labelMain/>
</mainLayout>
</panel>
<clickMeButton/>
</newComponent>
and then mainLayout.replaceComponent(labelMain, whatsWrongLabel).

mainLayout is not in the VerticalLayout, that's why the new component is simply added to it. You have to replace the panel's content.
Change
replaceComponent(mainLayout, new Label("what's wrong?"));
To
panel.setContent(new Label("what's wrong?"));

Related

Vaadin guides - how to add them correctly

Good afternoon everybody.
I am creating a sales system that looks like this until now.
It shows my grid without any sales, as I am still implementing the system, we can also see the existence of 3 buttons (New, Change, Delete). So far so good.
When I click on the New button, a window opens
With the window open as shown in annex 2, we have 3 tabs (Sales, Delivery and Financial).
Each tab must have its own form and each form must have its own components (ComboBox, TextField, DatePicker ... etc)
From here I have countless problems, all caused by my lack of experience in programming, after all it's only a few months since I started learning.
My first problem:
With the current code, if I click on any of the three tabs, the same form, with the same components are displayed (see annex 3 and annex 4).
How do I ensure that each guide has its form and each form has its components?
See my code:
package br.com.fjsistemas.cadastros.view;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.textfieldformatter.CustomStringBlockFormatter;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.tabs.Tab;
import com.vaadin.flow.component.tabs.Tabs;
import com.vaadin.flow.component.textfield.NumberField;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.binder.PropertyId;
import com.vaadin.flow.data.renderer.NumberRenderer;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import br.com.fjsistemas.backend.Venda;
import br.com.fjsistemas.main.MainView;
import br.com.fjsistemas.service.VendaService;
#Route(value = "venda-view", layout = MainView.class)
#PageTitle("Lançamento de Vendas")
public class VendaView extends VerticalLayout {
private static final long serialVersionUID = 1L;
private HorizontalLayout hltVenda = new HorizontalLayout();
Grid<Venda> grdVenda = new Grid<>(Venda.class, false);
private HorizontalLayout hltBarraBotoes = new HorizontalLayout();
Button btnNovo = new Button("Novo");
Button btnAlterar = new Button("Alterar");
Button btnExcluir = new Button("Excluir");
private Dialog dlgJanela = new Dialog();
private FormLayout fltCamposVenda = new FormLayout();
HorizontalLayout layoutGuiaVenda = new HorizontalLayout();
HorizontalLayout layoutGuiaVenda2 = new HorizontalLayout();
HorizontalLayout layoutGuiaVenda3 = new HorizontalLayout();
HorizontalLayout layoutGuiaVenda4 = new HorizontalLayout();
VerticalLayout layoutSeparar = new VerticalLayout();
VerticalLayout layoutSeparar2 = new VerticalLayout();
VerticalLayout layoutSeparar3 = new VerticalLayout();
#PropertyId("data")
private DatePicker txtDataVenda = new DatePicker("Data Venda");
#PropertyId("nomeCliente")
private TextField txtNomeCliente = new TextField("Nome Cliente");
#PropertyId("telefone")
private TextField txtTelefone = new TextField("Telefone");
#PropertyId("celular")
private TextField txtCelular = new TextField("Celular");
#PropertyId("produtos")
private ComboBox<String> txtProdutos = new ComboBox<>("Produtos");
#PropertyId("quantidade")
private NumberField txtQuantidade = new NumberField("Quantidade");
#PropertyId("unitario")
private TextField txtValorUnitario = new TextField("Valor Unitário");
#PropertyId("valorTotalVenda")
private NumberField txtValorTotalItem = new NumberField("Valor Total Item");
private HorizontalLayout htlDlgBarraBotoes = new HorizontalLayout();
private Button btnSalvar = new Button("Salvar");
private Button btnFechar = new Button("Fechar");
private Button btnAdicionarItem = new Button("Adicionar Item");
#Autowired
VendaService vendaService;
private List<Venda> listaVendas;
private Venda venda;
Binder<Venda> binderVenda = new Binder<>(Venda.class);
public VendaView() {
}
#PostConstruct
public void init() {
configuraTela();
}
private void configuraTela() {
setMargin(false);
setPadding(false);
configuraHltVenda();
configuraFltBarraBotoes();
configuraDlgJanela();
populaGrdVenda();
configuraBinder();
add(hltVenda, hltBarraBotoes);
}
private void configuraFltBarraBotoes() {
btnNovo.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnNovo.addClickListener(e -> {
novoClick();
});
btnAlterar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnAlterar.addClickListener(e -> {
alterarClick();
});
btnExcluir.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnExcluir.addClickListener(e -> {
excluirClick();
});
hltBarraBotoes.add(btnNovo, btnAlterar, btnExcluir);
}
private void excluirClick() {
if (venda != null) {
listaVendas.remove(venda);
vendaService.delete(venda);
atualizaGrdVenda();
}
}
private void configuraHltVenda() {
hltVenda.setWidthFull();
configuraGrdVenda();
hltVenda.add(grdVenda);
}
private void configuraGrdVenda() {
grdVenda.setHeight("820px");
grdVenda.setWidthFull();
grdVenda.addColumn(Venda::getId).setHeader("ID:").setAutoWidth(true);
grdVenda.addColumn(Venda::getDataVenda).setHeader("Data Venda:").setAutoWidth(true).setKey("dataVenda");
grdVenda.addColumn(Venda::getCliente).setHeader("Cliente:").setAutoWidth(true).setKey("cliente");
grdVenda.addColumn(new NumberRenderer<>(Venda::getValorTotalVenda, "R$ %(,.2f", Locale.getDefault(), "R$ 0.00"))
.setHeader("Valor Total:").setAutoWidth(true).setKey("valorTotalVenda");
grdVenda.addThemeVariants(GridVariant.LUMO_COMPACT, GridVariant.LUMO_COLUMN_BORDERS);
grdVenda.getColumns().forEach(col -> col.setAutoWidth(true).setSortable(true).setResizable(true));
grdVenda.addItemClickListener(e -> {
venda = e.getItem();
});
}
private void configuraDlgJanela() {
dlgJanela.setHeight("800px");
dlgJanela.setWidth("860px");
Tab vender = new Tab("Vendas");
Div venderDiv = new Div();
Tab entregar = new Tab("Entregas");
Div entregarDiv = new Div();
entregarDiv.setVisible(false);
Tab financeiro = new Tab("Financeiro");
Div financeiroDiv = new Div();
financeiroDiv.setVisible(false);
LocalDate now = LocalDate.now();
txtDataVenda.setValue(now);
txtNomeCliente.setWidth("380px");
new CustomStringBlockFormatter.Builder().blocks(0, 2, 4, 4).delimiters("(", ")", "-").numeric().build()
.extend(txtTelefone);
new CustomStringBlockFormatter.Builder().blocks(0, 2, 5, 4).delimiters("(", ")", "-").numeric().build()
.extend(txtCelular);
txtQuantidade.setHasControls(true);
Label valorTotalCompra = new Label("VALOR TOTAL DA COMPRA R$:");
valorTotalCompra.getStyle().set("margin-top", "112px");
TextField campoValorTotal = new TextField("Valor Total da Compra");
campoValorTotal.getStyle().set("margin-top", "100px");
layoutGuiaVenda.add(txtDataVenda);
layoutGuiaVenda2.add(txtNomeCliente, txtTelefone, txtCelular);
layoutGuiaVenda3.add(txtProdutos, txtQuantidade, txtValorUnitario, txtValorTotalItem);
layoutGuiaVenda4.add(valorTotalCompra, campoValorTotal);
fltCamposVenda.add(layoutGuiaVenda, layoutSeparar, layoutGuiaVenda2, layoutSeparar2, layoutGuiaVenda3,
layoutSeparar3, layoutGuiaVenda4);
vender.add(fltCamposVenda);
Map<Tab, Component> tabsToPages = new HashMap<>();
tabsToPages.put(vender, venderDiv);
tabsToPages.put(entregar, entregarDiv);
tabsToPages.put(financeiro, financeiroDiv);
Tabs tabs = new Tabs(vender, entregar, financeiro);
Div pages = new Div(venderDiv, entregarDiv, financeiroDiv);
tabs.addSelectedChangeListener(event -> {
tabsToPages.values().forEach(page -> page.setVisible(false));
Component selectedPage = tabsToPages.get(tabs.getSelectedTab());
selectedPage.setVisible(true);
});
dlgJanela.add(tabs, pages);
btnSalvar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnSalvar.getStyle().set("margin-top", "180px");
btnSalvar.getStyle().set("margin-left", "0px");
btnSalvar.addClickListener(e -> {
salvarClick();
});
btnFechar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnFechar.getStyle().set("margin-top", "180px");
btnFechar.addClickListener(e -> {
dlgJanela.close();
});
btnAdicionarItem.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
btnAdicionarItem.getStyle().set("margin-top", "180px");
btnAdicionarItem.addClickListener(e -> {
});
htlDlgBarraBotoes.add(btnSalvar, btnFechar, btnAdicionarItem);
dlgJanela.add(fltCamposVenda, htlDlgBarraBotoes);
}
private void salvarClick() {
venda = binderVenda.getBean();
boolean adicionarLista = venda.getId() == null ? true : false;
vendaService.create(venda);
if (adicionarLista) {
listaVendas.add(venda);
}
atualizaGrdVenda();
novaVenda();
txtNomeCliente.focus();
binderVenda.setBean(venda);
if (adicionarLista) {
dlgJanela.close();
}
}
private void populaGrdVenda() {
listaVendas = vendaService.read();
atualizaGrdVenda();
}
private void atualizaGrdVenda() {
grdVenda.setItems(listaVendas);
}
private void configuraBinder() {
binderVenda.bindInstanceFields(this);
}
private void novoClick() {
novaVenda();
binderVenda.setBean(venda);
dlgJanela.open();
txtNomeCliente.focus();
}
private void alterarClick() {
if (venda != null) {
binderVenda.setBean(venda);
dlgJanela.open();
}
}
private void novaVenda() {
venda = new Venda();
venda.setCliente(" ");
dlgJanela.close();
}
}
Welcome to the world of programming. You still certainly have a bunch to learn, but it is very good that you are jumping into something new and taking that challenge!
Looking at your tabs code. The tabs and the content seems to be okay. When a tab is clicked, you hide all contents, then you find the one that matches the clicked tab, and you turn visibility on on that one.
If I however read this correctly, vender is the tab button at the top, and you put in (somehow) all the form content into this tab header with vender.add(fltCamposVenda);. I think that row should be `venderDiv.add(fltCamposVenda);.
Now tabs seem to switch content between venderDiv, entregarDiv, and financeiroDiv, but they are all three empty divs, so nothing changes on the screen when you switch their visibilities!
Can I offer you two pieces of advice?
1: Consider coding in English. Even if it is not your native tongue, getting help becomes a bunch easier, and you won't mix two languages like Venda and VerticalLayout.
2: Consider splitting your view into smaller classes. Now you have a view, a grid, a dialog, a tabsheet, multiple forms, and probably more, all mixed up in the same class. Any part of this can access all other parts and cause unexpected errors, and understanding the code becomes harder. E.g. instead of private Dialog dlgJanela = new Dialog();, you could do public class JanelaDialog extends Dialog { in JanelaDialog.java, and then instead initialize it with JanelaDialog dlgJanela = new JanelaDialog(). This way you have the grid view in one class and the dialog component in another, and the code becomes easier to manage.
Good luck :)

Vaadin 14 - grid disappearing when using nested layout

After implementing nested layouts i faced the problem with rendering component containing grid. The analysis shows that is present in html but it has display-block attributes and the grid is never visible.
I read the similar question (Vaadin 14 - Grid not Displaying/Populating When Used in Nested Layout) but the suggestions listed there brought me no result.
Here comes my code:
MainLayout.kt:
#Theme(value = Material::class, variant = Material.DARK)
class MainLayout : Composite<Div>(), RouterLayout {
//Component to delegate content through.
private val mainContent: Div = Div()
private val layout = VerticalLayout(
Span("from MainLayout top"),
mainContent,
Span("from MainLayout bottom"))
override fun showRouterLayoutContent(hasElement: HasElement) {
Objects.requireNonNull(hasElement)
Objects.requireNonNull(hasElement.element)
mainContent.removeAll()
mainContent.element.appendChild(hasElement.element)
}
init {
content.add(layout)
}
}
LayoutWithMenuBar.kt:
#ParentLayout(value = MainLayout::class)
class LayoutWithMenuBar : Composite<Div>(), RouterLayout {
private val mainContent: Div = Div()
private val menuBar = HorizontalLayout(
RouterLink("Home", MainView::class.java),
RouterLink("Tprojects", TProjectDashboard::class.java),
RouterLink("ViewA", ViewA::class.java),
RouterLink("ViewB", ViewB::class.java))
private val root = VerticalLayout(menuBar, mainContent)
override fun showRouterLayoutContent(hasElement: HasElement) {
Objects.requireNonNull(hasElement)
Objects.requireNonNull(hasElement.element)
mainContent.removeAll()
mainContent.element.appendChild(hasElement.element)
}
init {
content.add(root)
}
}
and a component containing grid - TProjectDashboard:
#Route("dashboard/tproject", layout = LayoutWithMenuBar::class)
class TProjectDashboard(#Autowired val tprojectService: TProjectService): VerticalLayout() {
var tprojectGrid = Grid<TProject>(TProject::class.java)
init {
//tprojectGrid
tprojectGrid.setColumns(
TProject::tprojectUuid.name,
TProject::tprojectClass.name,
TProject::tprojectState.name,
TProject::tentityState.name,
TProject::size.name)
tprojectGrid.setItems(tprojectService.findAll())
tprojectGrid.setSizeFull()
tprojectGrid.setWidthFull()
tprojectGrid.setHeightFull()
add(tprojectGrid)
setSizeFull()
setHeightFull()
setWidthFull()
}
}
The same result i have when changing TProjectDashboard parent from VerticalLayout to Composite.
The nested layouts approach works well for simple components like Span and if i remove layout reference from #Route annotation i will see my grid.
Here is the screen how it looks like now:
enter image description here
Would appreciate for any hints or solutions.
Thanks in advance.
It's probably a sizing issue that unfortunately happens too often. I would start with calling setSizeFull() on the mainContent div. If that doesn't help, go through the elements in the browser devtools and try to see where the size disappears, e.g. what is the first element that has 0 width or height.
Edit: Setting setSizeFull() on all components works. I would simplify your layouts slightly, though, by changing the composites to be of type VerticalLayout. Then you can get rid of a lot of the setSizeFull() calls.
The code below is in Java as I don't have Kotlin set up, you can call getContent().setSizeFull() in MainLayout if you want it to take the full height of the page.
MainLayout
#Theme(value = Material.class, variant = Material.DARK)
public class MainLayout extends Composite<VerticalLayout> implements RouterLayout {
//Component to delegate content through.
private Div mainContent = new Div();
public MainLayout() {
getContent().add(
new Span("from MainLayout top"),
mainContent,
new Span("from MainLayout bottom"));
mainContent.setSizeFull();
}
#Override
public void showRouterLayoutContent(HasElement hasElement) {
Objects.requireNonNull(hasElement);
Objects.requireNonNull(hasElement.getElement());
mainContent.removeAll();
mainContent.getElement().appendChild(hasElement.getElement());
}
}
LayoutWithMenuBar
#ParentLayout(value = MainLayout.class)
public class LayoutWithMenuBar extends Composite<VerticalLayout> implements RouterLayout {
private Div mainContent = new Div();
private HorizontalLayout menuBar = new HorizontalLayout(
new RouterLink("Tprojects", TProjectDashboard.class));
public LayoutWithMenuBar() {
getContent().add(menuBar, mainContent);
mainContent.setSizeFull();
}
#Override
public void showRouterLayoutContent(HasElement hasElement) {
Objects.requireNonNull(hasElement);
Objects.requireNonNull(hasElement.getElement());
mainContent.removeAll();
mainContent.getElement().appendChild(hasElement.getElement());
}
}
TProjectDashboard
#Route(value = "dashboard/tproject", layout = LayoutWithMenuBar.class)
public class TProjectDashboard extends VerticalLayout {
private Grid<TProject> tprojectGrid = new Grid<>(TProject.class);
public TProjectDashboard() {
tprojectGrid.setItems(
new TProject("Erik", "Software Engineer"),
new TProject("Fia", "Kindergarden teacher"),
new TProject("Jack", "All trades")
);
add(tprojectGrid);
}
}

jface tableviewer tooltip text cut

I am using the jface tableviewer in an eclipse rcp application to display some values.
Therefore I have written the following snipped ...
tableviewer = new TableViewer(container, SWT.FULL_SELECTION | SWT.BORDER | SWT.SINGLE);
tableviewer.setContentProvider(new ArrayContentProvider());
ColumnViewerToolTipSupport.enableFor(tableviewer, ToolTip.RECREATE);
final Table table = tableviewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);
TableViewerColumn column = new TableViewerColumn(tableviewer, SWT.NONE);
column.getColumn().setText("col1");
column.getColumn().setResizable(true);
column.setLabelProvider(new ConfigLabelProvider("col1"));
And here here ConfigLabelProvider definition
private class ConfigLabelProvider extends StyledCellLabelProvider {
private String property;
public ConfigLabelProvider(String property) {
this.property = property;
}
#Override
public void update(ViewerCell cell) {
GenericConfigInterfaceEntity config = (GenericConfigInterfaceEntity) cell.getElement();
switch (property) {
case "col1":
cell.setText(AppHelper.preventNull("col1Text col1Text col1Text col1Text col1Text"));
break;
case ...
}
super.update(cell);
}
}
Now my problem is if the column is too small, the default tooltip is displayed trying to show the full cell text value.
BUT I get a tooltip box that is large enough for the whole text but the text isn't shown outside the cell rectange.
If I extend the ConfigLabelProvider from CellLabelProvider the Tooltip is showing up like expected ...
But I need the paint method of the StyledCellLabelProvider.
Any ideas?
Edit 1
I have written a small Java Example Project using SWT and JFACE, because my problems still remain.
My goal is to have an table with a cell-Background without the mousehover (because its looking ugly together) and a custom tooltip.
Here's my TestTable implementation
package main;
import java.util.ArrayList;
import java.util.List;
import model.TestModel;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.StyledCellLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
public class TestTable extends Dialog {
private TableViewer tableviewer;
private List<TestModel> entities;
protected TestTable(Shell parentShell) {
super(parentShell);
}
#Override
public void create() {
super.create();
loadData();
}
#Override
protected Control createDialogArea(Composite parent) {
GridData dataLayout;
Composite area = (Composite) super.createDialogArea(parent);
dataLayout = new GridData(GridData.FILL_BOTH);
dataLayout.heightHint = 150;
dataLayout.widthHint = 500;
Composite wrapper = new Composite(area, SWT.NONE);
wrapper.setLayoutData(dataLayout);
wrapper.setLayout(new FillLayout());
tableviewer = new TableViewer(wrapper, SWT.BORDER | SWT.MULTI);
tableviewer.setContentProvider(new ArrayContentProvider());
ColumnViewerToolTipSupport.enableFor(tableviewer);
final Table table = tableviewer.getTable();
table.setLinesVisible(true);
table.setHeaderVisible(true);
createColumns(wrapper);
return area;
}
private void createColumns(Composite wrapper) {
TableViewerColumn firstnameColumn = new TableViewerColumn(tableviewer, SWT.NONE);
firstnameColumn.getColumn().setText("Vorname");
firstnameColumn.setLabelProvider(new StyledCellLabelProvider(StyledCellLabelProvider.COLORS_ON_SELECTION) {
#Override
public void initialize(ColumnViewer viewer, ViewerColumn column) {
super.initialize(viewer, column);
this.setOwnerDrawEnabled(false);
}
#Override
public void update(ViewerCell cell) {
TestModel model = (TestModel) cell.getElement();
cell.setText(model.getFirstname());
cell.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_DARK_GREEN));
}
#Override
public String getToolTipText(Object element) {
TestModel model = (TestModel) element;
return "USE THIS AS TOOLTIP";
}
});
TableViewerColumn lastnameColumn = new TableViewerColumn(tableviewer, SWT.NONE);
lastnameColumn.getColumn().setText("Nachname");
lastnameColumn.setLabelProvider(new StyledCellLabelProvider(StyledCellLabelProvider.COLORS_ON_SELECTION) {
#Override
public void initialize(ColumnViewer viewer, ViewerColumn column) {
super.initialize(viewer, column);
this.setOwnerDrawEnabled(false);
}
#Override
public void update(ViewerCell cell) {
TestModel model = (TestModel) cell.getElement();
cell.setText(model.getLastname());
cell.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_DARK_GREEN));
}
#Override
public String getToolTipText(Object element) {
TestModel model = (TestModel) element;
return "USE THIS AS TOOLTIP";
}
});
for (TableColumn c : tableviewer.getTable().getColumns()) {
c.pack();
}
}
private void loadData() {
entities = new ArrayList<TestModel>();
entities.add(new TestModel("___Firstname1___", "Lastname1", "Username1", "Kommentar"));
entities.add(new TestModel("___Firstname2___", "Lastname2", "Username2", "Kommentar"));
entities.add(new TestModel("___Firstname3___", "Lastname3", "Username3", "Kommentar"));
entities.add(new TestModel("___Firstname4___", "Lastname4", "Username4", "Kommentar"));
entities.add(new TestModel("___Firstname5___", "Lastname5", "Username5", "Kommentar"));
tableviewer.setInput(entities);
tableviewer.refresh();
}
}
And here are some faulty pictures
Here the native TableViewer Tooltip and my custom ToolTip is shown, also the row gets selected (COLORS_ON_SELECTION should prevent that)
Here no tooltip is shown on the second column
And here no tooltip is shown and as you can see the first cell isn't filled up
If I add SWT.FULL_SELECTION the tooltip on column 2 appears but the other issues remain.
I think it's a kind of buggy that Tooltip Support or I am doing it totally wrong.
This solved my problem
https://stackoverflow.com/a/28991593/1822033
The underlaying second tip was shown because the column was too narrow. Setting tableviewer.getTavle().setTooltipText(""); stopped showing the native tip.
Setting it to null displays it anyway!

How to make a button to do something in Blackberry

I am trying to make a button that shows a message when it is pressed, but cannot get it to work.
Here is my button:
HorizontalFieldManager buttonManager =
new HorizontalFieldManager(ButtonField.FIELD_HCENTER);
messageButton = new ButtonField("Press me", ButtonField.CONSUME_CLICK);
messageButton.setChangeListener(this);
buttonManager.add(messageButton);
add(buttonManager);
And here is the method that prints the message:
public void fieldChanged(Field field, int context) {
if (field == messageButton) {
showMessage();
}
}
private void showMessage() {
Dialog.inform("The button was pressed");
}
Am I doing something wrong in the showMessage() method, or id the error elsewhere?
// just paste this class and run
package mypackage;
import java.io.IOException;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.MainScreen;
public final class MyScreen extends MainScreen
{
public MyScreen()
{
// Set the displayed title of the screen
HorizontalFieldManager horizontalFieldManager= new HorizontalFieldManager();
ButtonField buttonField= new ButtonField("click to show dialog",Field.FIELD_VCENTER);
horizontalFieldManager.add(buttonField);
buttonField.setChangeListener(buttonchangelisners);
add(horizontalFieldManager);
}
private FieldChangeListener buttonchangelisners= new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
// TODO Auto-generated method stub
showDialog("show your message");
}
};
public void showDialog(final String message) {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert(message);
}
});
}
}
Check the event log (Alt + LGLG), I suspect you'll see an error about pushing a modal screen on a non-event thread. If that is the case just change showMessage to
private void showMessage()
{
UiApplication.getUiApplication.invokeLater(new Runnable()
{
public void run()
{
Dialog.inform("The button was pressed");
}
});
}
I think the problem might be the flag CONSUME_CLICK you are passing to the constructor. If you want to do something with the button this is certainly not a flag you'd want to use.
Other than this, I'd advise against using FieldChangeListener for fields. Maybe for buttons is ok, but for other components the fieldChanged method might be called without user interaction during layout. This is why you almost always want to filter out those calls whose second parameter (context in your code) is equals to FieldChangeListener.PROGRAMMATIC.
A better alternative is to override navigationClick, which also works both for tactile and regular screens.
invokeLater is nevertheless useful, because fieldChanged is invoked at some point within a chain of UI Engine actions, and you'd better let it finish the job before displaying the Dialog. I suspect not using invokeLater is the main reason for the problem.
CONSUME_CLICK is in fact necessary when using fieldChangeListener, otherwise context menu will be invoked. If you switch to using navigationClick within your button field, you can return true to achieve the same behavior (though I prefer using navigationUnclick).

How to start a file download in vaadin without button?

I know that it is really easy to create a FileDownloader and call extend with a Button. But how do I start a download without the Button?
In my specific situation right now I have a ComboBox and the file I'd like to send to the user is generated after changing its value, based on the input. The file should be sent immediately without waiting for another click. Is that easily possible?
Thanks
raffael
I found a solution myself. Actually two.
The first one uses the deprecated method Page.open()
public class DownloadComponent extends CustomComponent implements ValueChangeListener {
private ComboBox cb = new ComboBox();
public DownloadComponent() {
cb.addValueChangeListener(this);
cb.setNewItemsAllowed(true);
cb.setImmediate(true);
cb.setNullSelectionAllowed(false);
setCompositionRoot(cb);
}
#Override
public void valueChange(ValueChangeEvent event) {
String val = (String) event.getProperty().getValue();
FileResource res = new FileResource(new File(val));
Page.getCurrent().open(res, null, false);
}
}
The javadoc here mentions some memory and security problems as reason for marking it deprecated
In the second I try to go around this deprecated method by registering the resource in the DownloadComponent. I'd be glad if a vaadin expert comments this solution.
public class DownloadComponent extends CustomComponent implements ValueChangeListener {
private ComboBox cb = new ComboBox();
private static final String MYKEY = "download";
public DownloadComponent() {
cb.addValueChangeListener(this);
cb.setNewItemsAllowed(true);
cb.setImmediate(true);
cb.setNullSelectionAllowed(false);
setCompositionRoot(cb);
}
#Override
public void valueChange(ValueChangeEvent event) {
String val = (String) event.getProperty().getValue();
FileResource res = new FileResource(new File(val));
setResource(MYKEY, res);
ResourceReference rr = ResourceReference.create(res, this, MYKEY);
Page.getCurrent().open(rr.getURL(), null);
}
}
Note: I do not really allow the user to open all my files on the server and you should not do that either. It is just for demonstration.
Here is my work-around. It works like a charm for me. Hope it will help you.
Create a button and hide it by Css (NOT by code: button.setInvisible(false))
final Button downloadInvisibleButton = new Button();
downloadInvisibleButton.setId("DownloadButtonId");
downloadInvisibleButton.addStyleName("InvisibleButton");
In your theme, add this rule to hide the downloadInvisibleButton:
.InvisibleButton {
display: none;
}
When the user clicks on menuItem: extend the fileDownloader to the downloadInvisibleButton, then simulate the click on the downloadInvisibleButton by JavaScript.
menuBar.addItem("Download", new MenuBar.Command() {
#Override
public void menuSelected(MenuBar.MenuItem selectedItem) {
FileDownloader fileDownloader = new FileDownloader(...);
fileDownloader.extend(downloadInvisibleButton);
//Simulate the click on downloadInvisibleButton by JavaScript
Page.getCurrent().getJavaScript()
.execute("document.getElementById('DownloadButtonId').click();");
}
});

Resources