How to disable a tab in a GXT 3 tabpanel - java

I have a GXT 3 TabPanel and would like to disable one or more tabs in response to an event.
There does not seem to be a way to do this.

PlainTabPanel panel = new PlainTabPanel();
TabItemConfig config = new TabItemConfig("Disabled");
Label disabled = new Label("This tab should be disabled");
config.setEnabled(false); // here what you need
panel.add(disabled, config);

I figured this out a while back and forgot to post the answer. Here's a way to do this that works reliably :
public class SimpleTabPanel extends com.sencha.gxt.widget.core.client.PlainTabPanel
implements TabPanel {
Tab currentActiveTab;
private Map<SimpleTab,TabItemConfig> tabConfigs = new HashMap<SimpleTab,TabItemConfig>();
// a map sorted by priority used to keep the expected tab order
SortedMap<TabData, SimpleTab> tabsConfig = new TreeMap<TabData, SimpleTab>(
new Comparator<TabData>() {
#Override
public int compare(TabData o1, TabData o2) {
return Float.compare(o1.getPriority(), o2.getPriority());
}
});
#Override
public Tab addTab(TabData tabData, String historyToken) {
SimpleTab newTab = createNewTab(tabData);
tabsConfig.put(tabData, newTab);
newTab.setTargetHistoryToken(historyToken);
return newTab;
}
private void disableTab(SimpleTab tab, TabData key){
// get and save tab's config.
TabItemConfig tic = getConfig(tab);
tabConfigs.put(tab, tic);
// put new one on tab to disable it.
tic = new TabItemConfig(key.getLabel());
tic.setEnabled(false);
update(tab, tic);
}
public void enableAllTabs(){
for(TabData key : tabsConfig.keySet()){
SimpleTab tab = tabsConfig.get(key);
TabItemConfig tic = tabConfigs.get(tab);
if(tic!=null){
tic.setEnabled(true);
update(tab, tic);
}
}
}
}

I had the same issue happening in my project.
The way I solved it is really simple and I hope that it answers your need.
public void enableTab(IsWidget item, Boolean enable) {
TabItemConfig config = tabPanel.getConfig(item.asWidget());
config.setEnabled(enable);
tabPanel.update(item.asWidget(), config);
}
I call that method every time I need to change a tab state.

Related

Vaadin Flow grid add an empty row

How can someone add a new empty line (perhaps at the bottom or at the top of the grid) programmatically.
At a later state the user enters data, or after some actions save all the rows perhaps in the database.
Technically it should be rather simple, especially if you use ListDataProvider for the Grid, here simplified example:
Grid<Bean> grid = new Grid<>(Bean.class);
ListDataProvider<Bean> dp = new ListDataProvider<>(getData());
grid.setDataProvider(dp);
add(grid);
Button button = new Button("Add row");
button.addClickListener(event -> {
Bean bean = new Bean();
dp.getItems().add(bean);
dp.refreshAll();
grid.getEditor().editItem(bean);
});
add(button);
You using ListDataProvider set fof dataprovider of grid.
Bean object Override hashCode method.
for Example :
#Transient
private long sId;
public ConstructorMethod () {
sId = System.currentTimeMillis();
}
#Override
public int hashCode() {
if (isNew())
return (int) (super.hashCode()+sId);
else
return super.hashCode();
}
New a bean object and add to ListDataProvider of grid
BeanClass item = new BeanClass();
(ListDataProvider<BeanClass>)grid.getDataProvider().getItems().add(item);
(ListDataProvider<BeanClass>)grid.getDataProvider().refreshAll();

How to make one action event for many chechbox'es?

I create an application in JavaFX where there is a lot of choicebox'es (around 100). Clicking each of them changes the status of one Boolean variable (selected - true, unselected - false). I have ActionEvent for each of choicebox, but I would like to make action event which suport all of them.
One of ActionEvent looks like:
public void onActionClick(ActionEvent actionEvent) {
if(firstCheckbox.isSelected()){
firstBooleanValue=true;
} else {
firstBooleanValue=false;
}
}
Second looks similar:
public void onActionClick(ActionEvent actionEvent) {
if(secondCheckbox.isSelected()){
secondBooleanValue=true;
} else {
secondBooleanValue=false;
}
}
I heard from my friend that I should create class with EventHandler and pass parameters (Checkbox and Boolean variable) but I don't know how. Any solutions?
I heard from my friend that I should create class with EventHandler and pass parameters (Checkbox and Boolean variable)
Unless you want to use a container class for the boolean variable (e.g. BooleanProperty), it's not really possible to pass a variable in a way that allows you to write it. You could of course pass a Consumer<Boolean>.
(Theoretically it would be possible to access fields via reflection to write a value, but I strongly recommend not doing this.)
In the event handler you could use the source property to get the object that triggered the change (the CheckBox). This fact would allow you to create a Map<CheckBox, Consumer<Boolean>> to handle the event with the same event handler without testing for reference equality with 100 CheckBoxes.
private boolean a;
private boolean b;
private boolean c;
private Map<CheckBox, Consumer<Boolean>> eventMap = new HashMap<>();
private void comboAction(ActionEvent event) {
CheckBox cb = (CheckBox) event.getSource();
eventMap.get(cb).accept(cb.isSelected());
}
#Override
public void start(Stage primaryStage) {
CheckBox cb1 = new CheckBox("a");
CheckBox cb2 = new CheckBox("b");
CheckBox cb3 = new CheckBox("c");
// tell event handler what to do with the booleans
eventMap.put(cb1, v -> a = v);
eventMap.put(cb2, v -> b = v);
eventMap.put(cb3, v -> c = v);
// register event handlers
EventHandler<ActionEvent> onAction = this::comboAction;
for (CheckBox cb : eventMap.keySet()) {
cb.setOnAction(onAction);
}
Button button = new Button("print");
button.setOnAction(evt -> {
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println("-------");
});
Scene scene = new Scene(new VBox(cb1, cb2, cb3, button));
primaryStage.setScene(scene);
primaryStage.show();
}
However the fact that there are 100 boolean fields in a single class indicates a design issue. Consider storing the data in a different data structure, like List, Map or similar data structures. You could also store the CheckBoxes in such a data structure which would make the use of an onAction event handler unnecessary; you could simply retrieve the CheckBox responsible for the property and use isSelected when you need the value...

How to clear the field after i set ComboBox value as null?

I have a ComboBox called projectRequirementComboBox that is dependent from projectComboBox, from where I get the list to show in the dropdown in projectRequirementComboBox, but I want to do something like: when a user changes the project I want to empty projectRequirementComboBox, to be more clear none of the item will not be selected I am doing this right now but still my projectRequirementComboBox has the old value, I don't know what am I missing .I am using vaadin.version 8.0.7 .
private void refreshProjectRequirementCombobox()
{
List<ProjectRequirement> projectRequirements = new ArrayList<>();
if (projectComboBox.getValue() != null)
{
projectRequirements = projectRequirementService.findCurrentProjectRequirements(projectComboBox.getValue().getProjectId());
}
projectRequirementComboBox.setItems(projectRequirements);
projectRequirementComboBox.setValue(null);
}
private void loadProjectRequirement(Project project)
{
List<ProjectRequirement> projectRequirements = new ArrayList<>();
if (project != null)
{
projectRequirements = projectRequirementService.findCurrentProjectRequirements(project.getProjectId());
}
projectRequirementComboBox.setItems(projectRequirements);
}
I call refreshProjectRequirementCombobox here.
projectComboBox.addValueChangeListener(event ->
{
refreshProjectRequirementCombobox();
loadRejectReason();
});
Normally this should work. I created a minimum example with two ComboBoxes "main" and "dependent". The selection of the dependent ComboBox depends on the selection of the main ComboBox. Therefore there is a ValueChangeListener on the main ComboBox that resets the items and the selected value of the dependent ComboBox. When you start the application you see that the offered items of the dependent ComboBox change and that none of these new items is selected.
I think you have to post more of your code (where do you call refreshProjectRequirementCombobox from?) to see what you are doing different.
Here is my example minimum project code:
#Override
protected void init(VaadinRequest vaadinRequest) {
final VerticalLayout layout = new VerticalLayout();
final ComboBox<String> main = new ComboBox<>();
final ComboBox<String> dependent = new ComboBox<>();
final Map<String, String[]> dependentsByMain = new HashMap<>();
dependentsByMain.put("A", new String[]{"AA", "AB", "AC"});
dependentsByMain.put("B", new String[]{"BA", "BB", "BC"});
dependentsByMain.put("C", new String[]{"CA", "CB", "CC"});
List<String> mainItems = new ArrayList<>(dependentsByMain.keySet());
main.setItems(mainItems);
dependent.setItems(Arrays.asList("Test1", "Test2", "Test3"));
dependent.setValue("Test1");
main.addValueChangeListener((HasValue.ValueChangeListener<String>) valueChangeEvent -> {
if (valueChangeEvent.getValue() != null) {
dependent.setItems(dependentsByMain.get(valueChangeEvent.getValue()));
dependent.setValue(null);
}
});
layout.addComponents(main, dependent);
setContent(layout);
}
UPDATE:
Have a look at Srinivasan Sekar's answer and its comments. This is a bug in the used version (8.0.7) which seems to be fixed in version 8.5 (according to https://github.com/vaadin/framework/issues/9047#issuecomment-437864866). I tried my example code with version 8.7.1 so it works. With version 8.0.7 it doesn't.
So the main solution is to update the used Vaadin version. As a workaround (when unable to upgrade the Vaadin version) you FIRST have to set the ComboBox's value to null and THEN set the new items. So in my example the ValueChangeListener must look like:
main.addValueChangeListener((HasValue.ValueChangeListener<String>) valueChangeEvent -> {
if (valueChangeEvent.getValue() != null) {
dependent.setValue(null);
dependent.setItems(dependentsByMain.get(valueChangeEvent.getValue()));
}
});
There is open issue in Vaadin https://github.com/vaadin/framework/issues/9566 which refers to https://github.com/vaadin/framework/issues/2813
Going through the issue I found that by creating a custom combobox you can fix the issue:
public class ClearableComboBox<T> extends ComboBox<T> {
public ClearableComboBox(String in) {
super(in);
}
protected void setSelectedFromServer(T item) {
String key = itemToKey(item);
T oldSelection = getSelectedItem().orElse(getEmptyValue());
doSetSelectedKey(key);
fireEvent(new SingleSelectionEvent<>(ClearableComboBox.this, oldSelection, false));
}
}
Additionally, make sure to call setValue before calling setItems to clear items.
cmb.setValue(null);
cmb.setItems(aEmptyCollection);

nattable: how to disable single cell selection?

How to disable single cell selection when clicking? Example
I'm trying it that way:
class CustomDefaultSelectionBindings extends DefaultSelectionBindings {
#Override
protected void configureBodyMouseClickBindings(final UiBindingRegistry uiBindingRegistry) {
//do nothing
}
}
class CustomDefaultSelectionLayerConfiguration extends DefaultSelectionLayerConfiguration {
#Override
protected void addSelectionUIBindings() {
addConfiguration(new CustomDefaultSelectionBindings());
}
}
final SelectionLayer selectionLayer = new SelectionLayer(bodyDataLayer);
selectionLayer.addConfiguration(new CustomDefaultSelectionLayerConfiguration());
Thanks in advance.
You need to create the SelectionLayer without the default configuration
final SelectionLayer selectionLayer = new SelectionLayer(bodyDataLayer, false);
selectionLayer.addConfiguration(new CustomDefaultSelectionLayerConfiguration());
But with the above solution you could still select in the body because of the body mouse drag mode. The easy way would be to not using the SelectionLayer anyhow. Not sure about the other requirements you have.

Remove a generated panel in GWT after a button is clicked

I am attempting to create a Google Web Toolkit (GWT) application that also uses Google Gears, but every time I try to remove the panel, I get an exception and the panel stays there.
Here is an excerpt from the exception I get (I've only included the relevant bits of the call stack, the rest just descends into the included function below):
java.lang.AssertionError: A widget that has an existing parent widget may not be added to the detach list
at com.google.gwt.user.client.ui.RootPanel.detachOnWindowClose(RootPanel.java:122)
at com.google.gwt.user.client.ui.RootPanel.get(RootPanel.java:197)
I'm not sure what the problem is, but I really don't like leaving the button there after they approve the use of Gears.
What am I doing wrong? Or any suggestions on a different way I could do this to make it work?
if(!gearsFactory.hasPermission()) {
HorizontalPanel rightPanel = new HorizontalPanel();
rightPanel.getElement().setId("gearsPrompt");
rightPanel.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
rightPanel.setSpacing(0);
rightPanel.setHeight("28px");
InlineLabel enableGearsText = new InlineLabel("Enable Gears for off-line access");
enableGearsText.getElement().setId("gearsText");
enableGearsText.addStyleName("titleElement");
rightPanel.add(enableGearsText);
final Button gearsButton = new Button("Use Gears");
gearsButton.getElement().setId("gearsButton");
gearsButton.addStyleName("titleElement");
gearsButton.setHeight("24px");
gearsButton.addClickHandler( new ClickHandler() {
public void onClick(ClickEvent event) {
Factory gearsFactory = Factory.getInstance();
if(gearsFactory != null) {
if(gearsFactory.getPermission()) {
RootPanel gearsPrompt = RootPanel.get("gearsPrompt");
gearsPrompt.removeFromParent();
}
}
}
});
rightPanel.add(gearsButton);
RootPanel titleBarRight = RootPanel.get("titleBarRight");
titleBarRight.add(rightPanel);
}
One solution I've found is to loop through all of the widgets under the "titleBarRight" panel and remove all widgets it contains:
if(gearsFactory.getPermission()) {
RootPanel titleBarRight = RootPanel.get("titleBarRight");
java.util.Iterator<Widget> itr = titleBarRight.iterator();
while(itr.hasNext()) {
itr.next();
itr.remove();
}
}
But somehow this still seems hacky and not quite the "right way to do it."
I know this is old, but how about...
gearsButton.addClickHandler( new ClickHandler() {
public void onClick(ClickEvent event) {
Factory gearsFactory = Factory.getInstance();
if(gearsFactory != null) {
if(gearsFactory.getPermission()) {
Button btn=(Button) event.getSource();
btn.removeFromParent();
}
}
}
});
Is there any reason for using RootPanel.get("gearsPrompt").removeFromParent(); instead of your own rightPanel.removeFromParent();? The reference is already there.
You can do :
theParentWidget.remove(index);
and the first child corresponds to 0;

Categories