I have a GXT 3 app and I'm trying to use a ToggleButtonCell to allow the user to modify a Boolean value.
Here's the code for the data:
public class InspectionListGridData {
private Boolean posted;
public InspectionListGridData(InspectionListGridData dataToCopy) {
setPosted(dataToCopy.getPosted());
}
public Boolean getPosted() {
return posted;
}
public void setPosted(Boolean posted) {
this.posted = posted;
}
}
For the grid to access the data, I provide this property access interface:
interface ListProperties extends PropertyAccess<InspectionListGridData> {
ValueProvider<InspectionListGridData, Boolean> posted();
}
The Grid & column config are declared like this:
final ListProperties properties = GWT.create(ListProperties.class);
final List<ColumnConfig<InspectionListGridData,?>> columnConfigList = new ArrayList<ColumnConfig<InspectionListGridData,?>>();
final ListStore<InspectionListGridData> store = new ListStore<InspectionListGridData>(
new ModelKeyProvider<InspectionListGridData>() {
#Override
public String getKey(InspectionListGridData item) {
return item.getInspectionDocumentId().toString();
}
}
});
final ColumnConfig<InspectionListGridData, Boolean> postedColumnConfig = new ColumnConfig<InspectionListGridData, Boolean>(properties.posted(), 5, "Posted");
ToggleButtonCell postedButtonCell = new ToggleButtonCell();
postedButtonCell.setText("posted");
postedButtonCell.setIcon(SafedoorPM.localizedResources.postedIcon());
postedButtonCell.setIconAlign(IconAlign.TOP);
postedColumnConfig.setCell(postedButtonCell);
postedColumnConfig.setSortable(false);
columnConfigList.add(postedColumnConfig);
Grid<InspectionListGridData> inspectionListGrid = new Grid<InspectionListGridData>(store, columnModel);
When I load this screen, the buttons do not initialize to the corresponding state indicated by the data. [EDIT: the failed loading of initial values was due to a different bug. Once I fixed that the initial values loaded correctly]
Once the screen is loaded, if I click a button it changes state just fine but the store doesn't get updated. I set breakpoint on the InspectionListGridData.setPosted() method, it is not called when I click on the button.
Can anyone see what I'm doing wrong? Or am I just wrong in thinking this is supposed to just work? I thought that was the point of the ValueProvider interfaces.
Bonus extra weirdness, the grid displays the red triangle in the corner to indicate that the cell is dirty when it is clicked and button does display properly when clicked i.e. it stays down or up. It just doesn't seem to read or update the data store.
Two questions here, at first I only keyed off of the first one (which I still can't answer, but more info might help), but the second is very clear.
When I load this screen, the buttons do not initialize to the corresponding state indicated by the data.
This is confusing, and contradicted by a quick sample I put together, as I indicated in my comment It could be that you are changing the data after drawing the grid and not informing the store or grid that the data has changed, but if you are building the data with both true and false values, the grid should be displaying with both true and false values.
I set breakpoint on the InspectionListGridData.setPosted() method, it is not called when I click on the button.
By default, this is expected while store.isAutoCommmit() is true, which is the default value. This tells the store that it should queue up changes rather than applying them directly to the objects in the store. These changed values are marked in the UI with the red triangle you noticed, and other code can check for changed values through the Store.getRecord(M) method or Store.getModifiedRecords() calls. Calling store.commitChanges() will apply all of them to the underlying models, or you can commit to specific models with Record.commit(). You can also reject changes with Store.rejectChanges() or Record.revert().
When this is turned off, the setPosted method should be called by clicking the button. No change tracking can occur, so no dirty flag will be set, either visually or in the store's records.
If you change an object that is already rendered, you have two (main) choices - you can modify the object directly via its setters and inform the store, or you can use the store's record objects. If autocommit is false and you invoke store.getRecord(object).addChange(properties.posted(), true), then instead of creating a new change to be committed, this will call setPosted(true), so these methods are effectively the same when autocommit is false. If you directly call a setter, be sure to inform the store that the object has changed via store.update.
Related
I have Eclipse JFace wizard with five pages. In the first, I have check buttons to select which pages are to be shown - if you check all, you will pass through the whole wizard, but you can also select only specific pages, and then only that pages will be shown.
So far, I used iterator with enum objects representing each page. I called next object of iterator in getNextPage function and its if..else cases to return certain pages in proper order. The problem is, getNextPage is called not only when Next button is pressed, but also when pageComplete event firing, etc. so iterator does not update its cursor when I want, and it ends up to fast. This is snippet of my assumption:
else if(page == FirstPage )
{
// iterator contains SelectedAction - enum objects representing pages
this.pageIterator = page.getWizardPagesList().iterator();
if(pageIterator.hasNext())
{
return selectedActionToPage(pageIterator.next());
}
}
else
{
if(pageIterator.hasNext())
{
SelectedAction action = pageIterator.next();
if(!pageIterator.hasNext())
{
// we check if current page was last one
setFinished(true);
setLastPage(selectedActionToPage(action));
}
// selectedActionToPage converts enum object to WizardPage class
return selectedActionToPage(action);
}
else if((pageIterator != null) && !pageIterator.hasNext())
{
return page;
}
}
return page;
Especially, things I want to know are:
First, is there any other way to capture Next button click? I know there is NextPressed method in WizardDialog class, but I don't know how to call its instance from my Wizard class, or WizardPage.
Second, is there other way to customize navigation through pages, to go to specified pages?
No, you should not try to intercept the Next button click that logic is private to the wizard dialog and you should not be trying to interfere with it,
You can either override the WizardPage:
public IWizardPage getNextPage()
method or you can override the Wizard
public IWizardPage getNextPage(IWizardPage page)
You may also need to override the matching getPreviousPage method. You must make your code work regardless of when the method is called. You are given the information about which is the current page, your code should use that to determine the next page.
I have run into pretty messed up behaviour with my ListView, I have listview created in controller with data attached to it.
#FXML
private ListView<Weapon> listViewWeapons;
...
private final ObservableList<Loadout> loadoutList;
public LoadoutViewController() {
...
loadoutList =FXCollections.observableList(CsgoRr.getModel().getLoadoutCache());
...
}
#Override
public void initialize(URL location, ResourceBundle resources) {
...
listViewLoadouts.setItems(loadoutList);
...
}
I call method attached to button, which has function of adding new loadout into list
#FXML
private void newLoadoutOnAction() {
try {
Loadout loadoutToBeStored = new Loadout(new Long[10], "Loadout" + newDuplicateNameLoadoutIncrement);
loadoutToBeStored.setId(DbUtil.storeLoadout(loadoutToBeStored));//store and set id.
CsgoRr.getModel().getLoadoutCache().add(loadoutToBeStored);
System.out.println("Stored new loadout ");
listViewLoadouts.getSelectionModel().select(loadoutToBeStored);
for (Loadout loadout : loadoutList) {
System.out.println("DEBUG LOADOUT CONTAINER OBSERVABLE:" + loadout);
}
} catch (SQLException ex) {//duplicate name
if (ex.getErrorCode() == 23505) {
newDuplicateNameLoadoutIncrement++;
newLoadoutOnAction();
}
Logger.getLogger(LoadoutViewController.class.getName()).log(Level.SEVERE, null, ex);
}
}
All the data is correctly loaded and stored, I have debugged that part of course. But even though I call method newLoadoutOnAction and I put data into list which observable list has reference to, change is not seen up until I resize that listView. That's not the only problem, even after I resize listView and I'm able to see item in a list I can't select it I have to call construstor and initializer again to be able to select this item. I have never encountered this behaviour, how do I fix these problems?
Problem with refreshing item in the list: I have tried to remove items and set them again, and some other solutions common to this problem bud nothing worked even if I put setItems(null) I can't get it to work, items are still there.
Latest item inserted is not selectable (through UI) until I call my controller again and recreate everything. I have this item selected with code.
listViewLoadouts.getSelectionModel().select(loadoutToBeStored);
This actually selected needed item bud I don't see any feedback in the UI and I can't select it with my mouse. Even if I remove this line I still can't select it with a mouse till I call my view again (constructor and initializer).
I know this is a bit more complex problem so I decided to show you what's happening with a gif.
Hope it's clear.
The Javadoc for FXCollections.observableList states:
Note that mutation operations made directly to the underlying list are not reported to observers of any ObservableList that wraps it.
For this reason loadoutList is not connected to the list in CsgoRr.getModel().getLoadoutCache() after creation. This means that when newLoadoutOnAction() calls:
CsgoRr.getModel().getLoadoutCache().add(loadoutToBeStored);
it is not picked up by loadoutList, or the ListView watching it. If you change CsgoRr.getModel().getLoadoutCache() to use an ObservableList, and assign that directly to loadoutList your function should work as desired.
The other option would be to add your loadoutToBeStored to loadoutList instead, but then you would need to also synchronise with the List in CsgoRr.getModel()
This is my code:
comboBoxInstance.setInputPrompt("Something...");
comboBoxInstance.setNullSelectionAllowed(false);
Cookie comboCookie = getCookieByName("combo");
comboBoxInstance.select((comboCookie != null) ? comboCookie.getValue() : null);
final TextField textFieldInstance = new TextField("Textfield");
textFieldInstance.setInputPrompt("Something...");
Cookie tfCookie = getCookieByName("tf");
textFieldInstance.setValue((tfCookie != null) ? tfCookie.getValue() : null);
The problem is that the textfield works pretty well with the "Cookie setup". Only the combobox is refusing to work like it should.
The output is like this:
I've tried to use .setValue() instead of .select() but this has pretty much the same effect. I've also made sure that both the Cookie itself and the correct value are provided.
It may help to have a look at the part where the cookie is generated:
Cookie comboCookie = new Cookie("combo", comboBoxInstance.getValue().toString());
cookieProcessing(costcentreCookie); //<- sets maxage and vaadin related stuff (like adding the cookie)
Edit:
A few points to the data flow.
I'm generating a ComboBox with a SimpleJDBCConnectionPool's SQLContainer as the data container (coming from a TableQuery). Here's the initialization (executed in the constructor) in the combobox class:
private void init() throws SQLException {
this.setContainerDataSource(generateContainer());
this.setItemCaptionPropertyId("something");
}
The private method generateContainer() returns the SQLContainer of course.
This happens if I click on a particular button which opens up a dialog. This dialog is the fragment shown in the picture above. The combobox - of course - is part of it.
What one is supposed to do now is setting his data (get an item of the ComboBox) and hit save. The save button executes the routine to store the cookies. It's the code already mentioned above (Cookie comboCookie = new Cookie(...).
Okay, now the user is going to open up the dialog again. It's not important whether he reloads the application or just reopens the dialog (or does something else). It's basically the same in the app.
The dialog opens up and initializes the combobox (and the textfield) once again. However, this time it's supposed to gather the data out of the stored cookies. This is were the issue happens. This works well for the textfields (there are two but I've omitted one for shortening reasons) but not for the combobox, even tough it should've the exact same data as before. Hold in mind that it's the exact same class with the exact same initialization as when we stored the cookies in the first place.
I've the vague presumption, that it has to do something how the code is stacked. Maybe it hasn't finished loading the datacontainer while trying to set the appropriated value which then can't be found.
Edit2:
I've finally managed to reveal something. The ComboBox is indeed empty when the ".select()" is executed. However, this means, that the ComboBox is left untouched (it's only kind of "linked" to the datacontainer) until someone drops down the items. As soon as this happens, the items are there and I can possibly select them.
Is it supposed to work like this? O.o Am I able to fully initialize the combobox before I do something else? Something like:
private void init() throws SQLException {
this.setContainerDataSource(generateContainer());
this.setItemCaptionPropertyId("something");
this.gatherTheItems();
}
Edit3 - Test with ".setImmediate(true)"
I've changed the init to:
private void init() throws SQLException {
this.setContainerDataSource(generateContainer());
this.setItemCaptionPropertyId("SOMETHING");
this.setImmediate(true);
}
This didn't change anything. The combobox is still empty:
Finally! At first I've found a workaround which was like this:
for (Iterator it_IDS = combobox.getItemIds().iterator(); it_IDS.hasNext();) {
Object id = (Object) it_IDS.next();
if(id.toString().equals(cookie.getValue().toString())){
combo2.select(id);
break;
}
}
However, I couldn't believe that this was working since it doesn't change anything at the core problem. So I've investigated, that the RowID is built via a BigDecimal and voilĂ :
if(cookie != null) {
combobox.select(new RowId(new BigDecimal(cookie.getValue())));
}
I'm so happy right now :) Thanks for your patience kukis.
In case you came here because you're experiencing the same issue using a BeanItemContainer as datasource, bear in mind that you must implement both equals()and hashCode() methods on the underlying class for ComboBox's select() or setValue() methods to work.
You have plenty examples on Vaadin Forum on how to implement these methods:
ComboBox select value problem
Select or ComboBox does not Show Selected Property
Combobox select/setValue
TLDR:
I'm setting myListView.setVisibility(View.GONE);, but it's not dissappearing until later... do I need to let it know somehow that I've changed it's visibility? Or do I need to also hide it's inner elements or something?
Description of Problem:
I have a normal news app. You see a list of articles for the "main" section, then you can click the options to select a new section.
When the user clicked, the section title changed, but the articles in the list would just sit there with "old" content until the new content is loaded, then it would flash to the new content.
This isn't ideal obviously. I'd like the list to disappear, show a loading animation, then, after the new data is retrieved (either from DB or online, then DB), it shows the new content.
I found this SO question which seemed like what I want, but...
I'm setting GONE immediately upon selection of the menu, then VISIBLE after it import the articles and loads the new ones... but it's not disappearing at all during that. I know the GONE code works, because if I remove my VISIBLE code, the articles never reappear.
Do I need to say "View.GONE", then tell it to update it's visibility or something?
My Code (MainActivity):
public static void sectionSelected()
{
String selectedText = sectionsSpinner.getSelectedItem().toString();
String[] selectedSection = Section.stringToSection(selectedText);
//check if it was already the current section
if(!Section.isEqual(Section.currentSection, selectedText))
{
//hides list of articles
articleEntryListView.setVisibility(View.GONE);
//sets new currentSection
Section.currentSection = selectedSection; // Section.stringToSection(sectionsSpinner.getSelectedItem().toString());
//imports articles (if it's been more than an hour since last import)
articlesDataSource.importArticles(Section.currentSection, true, false);
//loads article from database to the list
loadArticlesIntoList(Section.currentSection);
}
}
public static void loadArticlesIntoList(String[] section)
{
//clears the list
//articleEntryAdapter.clear(); //don't think I need this now that I'm just going to hide it
//articleEntryAdapter.notifyDataSetChanged();
//POPULATES THE LIST OF ARTICLES, THROUGH THE ADAPTER
for(final Article a1 : articlesDataSource.getArticles(section))
{
articleEntryAdapter.add(a1);
}
articleEntryAdapter.notifyDataSetChanged();
//shows list of articles
articleEntryListView.setVisibility(View.VISIBLE);
}
ADDITION: here is my importAricles() code: http://pastebin.com/8j6JZBej
You have to invalidate the view anytime you make a change to its appearance, so make a call to articleEntryListView.invalidate() after setting the visibility.
I'm trying to create a menu screen, and I want to be able to create it, and any further permutations of it dynamically. I've created a MenuItem helper class to handle the menu items that show up, and it reads the name, image, and set the next state (something that is handled later). What I want to know is, how can I create the specific following Screens (they'll all be some subclass of my Screen class)?
What is the most efficient method to pass specific objects into the menuItems? Do I need to pre-create each possible Screen and then just read back in the serialized form of it, or can I create them dynamically. I'd hoped to be able to do something as simple as reading in a literal string "new SubClass(...)" and act off that, but I don't know how to go about that. Any other suggestions would be great!
If I understand correctly, what you want is a mechanism that reads a String command from a text file, and based on this command, displays a screen.
So, extract the interface of the "display screen" command into an interface. For example:
public interface ScreenDisplayer {
void displayScreen(Screen mainScreen);
}
Then build a Map<String, ScreenDisplayer>:
map.put("screen1", new ScreenDisplayer() {
#Override
void displayScreen(Screen mainScreen) {
// TODO display screen 1
});
// same for all the other commands
And when a "menu item" is clicked, get the DisplayScreen from the map and call it:
String command = selectedMenuItem.getCommand();
ScreenDisplayer displayer = map.get(command);
displayer.displayScreen(mainScreen);