Combobox doesn't react to ".setValue()" nor ".select()" - java

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

Related

JavaFX ListView adding item into observable list doesn't reflect change and it's not selectable

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()

GXT 3 ToggleButtonCell not updating data store

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.

List View - setting View.GONE upon menu selection doesn't hide immediately

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.

Wicket panels need page refresh for javascript script to work

I am creating a web page with several tabs. To implement that I am using wicket AjaxTabbedPanel and several AbstractTab. In each tab I have tables with data and I am using a javascript script to make the tables sortable.
public TabbedPage() {
List<ITab> tabs = new ArrayList<ITab>();
tabs.add(new AbstractTab(new Model<String>("first tab")) {
public Panel getPanel(String panelId) {
return new TablePanel(panelId);
}
});
tabs.add(new AbstractTab(new Model<String>("second tab")) {
public Panel getPanel(String panelId) {
return new TablePanel(panelId);
}
});
add(new AjaxTabbedPanel("tabs", tabs));
}
When I load the page the table in the tab selected by default is sortable. However, as soon as I click any of the links to jump to other tabs (including the one of the tab already selected), none of the tables in any of the tabs allows me sort them (including the one that was previously working - the table in the default tab). If I refresh the page I can sort the table (of the tab selected in the moment of the refresh), but as soon as I click in any of links to switch tabs, the tables stop having the sortable capability again. Any ideas of why is this happening?
EDIT:
I just found that if I replace the AjaxTabbedPanel by TabbedPanel I don't have this problem. Although I'm still not sure why is that. Can anyone enlighten me?
add(new TabbedPanel("tabs", tabs));
Sorting the table by JavaScript is most likely a function called with a specific DOM-Id and seems to be executed 'onLoad'. it then accesses the currently displayed table and does it's work.
Changing the content of your Panel by Ajax doesn't trigger 'onLoad' so the function isn't executed again. TabbedPanel reloads the page and therefore executed your script.
Selecting a previous sortable table with AjaxTabbedPanel doesn't work because of the dynamically generated DOM-Ids.
Your solution is to add a AjaxCallDecorator to the links from AjaxTabbedPanel or to include the script or at least the function call to your tabbed panels.
At least this it what comes to mind without seeing any sources...
EDIT:
You might want to look at The Wicket Wiki. There's a description on how to call js after clicking an AjaxLink. That's exactly what should solve your problem.
Summary: Just add
link.add(new AttributeAppender("onclick", new Model("myTableSortingScript();"), ";"));
to the links generated by AjaxTabbedPanel.
In Wicket 6.0 you can run JavaScript on a component basis: Just override renderHead(IHeaderResponse response) for your component:
#Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
response.render(new OnLoadHeaderItem("initalizeMe(\"" + getMarkupId() + "\");"));
}
initializeMe(mycomponentId) is executed every time the component is loaded by the AjaxTabbedPanel. This also works with the standard TabbedPanel.
No real idea since I'm not sure what the code is doing but I had a similar problem with my Panel Manager. Basically if you dynamically load HTML into a panel (a div or another element) using "innerhtml" script in the content will not be executed.
To get around this I scan the loaded content for "script" tags and append them using the DOM methods - this does run the script and makes it available. My "load" method is:
// Load Content
Panel.load = function(Content) {
// "null" the old (to clear it)
Panel.innerHTML = null;
// Load the content
Panel.innerHTML = Content;
// Load Scripts
var AllScripts = Panel.getElementsByTagName("script");
var AllScriptsCnt = AllScripts.length;
for (var Cnt = 0; Cnt < AllScriptsCnt; Cnt++){
var CurScript = document.createElement('script');
CurScript.type = "text/javascript";
CurScript.text = AllScripts[Cnt].text;
Panel.appendChild(CurScript);
};
};
Again, not sure if this is the issue, but it sounds pretty much on target from my experience.

Adding figures using contextual menu - Eclipse GEF

All,
I am creating a palette less eclipse plugin where am adding figures to the custom editor through the contextual menu, but am not finding a way to do it. Can anyone please guide me as to how to go about adding figures to editor dynamically through context menu i.e. adding actions/commands.
Since Eclipse GEF plugin development finds so less examples to look at, I am adding my solution so others find it useful. This code helps to render a node to the editor.
Source code for Action class to render figures to the editor:
public class AddNodeAction extends EditorPartAction
{
public static final String ADD_NODE = "ADDNODE";
public AddNodeAction(IEditorPart editor) {
super(editor);
setText("Add a Node");
setId(ADD_NODE); // Important to set ID
}
public void run()
{
<ParentModelClass> parent= (<ParentModelClass>)getEditorPart().getAdapter(<ParentModelClass>.class);
if (parent== null)
return;
CommandStack command = (CommandStack)getEditorPart().getAdapter(CommandStack.class);
if (command != null)
{
CompoundCommand totalCmd = new CompoundCommand();
<ChildModelToRenderFigureCommand>cmd = new <ChildModelToRenderFigureCommand>(parent);
cmd.setParent(parent);
<ChildModelClass> newNode = new <ChildModelClass>();
cmd.setNode(newNode);
cmd.setLocation(getLocation()); // Any location you wish to set to
totalCmd.add(cmd);
command.execute(totalCmd);
}
}
#Override
protected boolean calculateEnabled()
{
return true;
}
}
I think you need multiple different things here. Please remember that GEF would like you to have proper MVC pattern, where you have your own model, Figures as View and EditParts as controllers.
From the top of my head I would say that you need at least these things:
CreateCommand
contains all model level modifications that you need to
perform to add your new data to your
data model (undoable and transactional)
CreateAction
makes that CreateCommand instance, initializes it with current selection and executes that command in editdomain
ContextMenuProvider
Provides that CreateAction to context menu
If you happen to be using GMF the canonical mechanism will generate the editparts for you automatically when you make the model modifications inside a command, but if you are not using GMF, you must make sure that your own models and editparts are handling and refreshing the new item adding properly.
EDIT:
Ok, here is some code suggestion with playing around with requests.
public void run() {
// Fetch viewer from editor part (might not work, if not, try some other way)
EditPartViewer viewer = (EditPartViewer) part.getAdapter(EditPartViewer.class);
// get Target EditPart that is under the mouse
EditPart targetEditPart = viewer.findObjectAt(getLocation());
// If nothing under mouse, set root item as target (just playing safe)
if(targetEditPart == null)
targetEditPart = viewer.getContents();
// Make and initialize create request with proper information
CreateRequest createReq = new CreateRequest();
createReq.setLocation(getLocation());
createReq.setFactory(new OwnFactoryImplementation());
// Ask from target editpart command for this request
Command command = targetEditPart.getCommand(createReq);
// If command is ok, and it can be executed, go and execute it on commandstack
if(command != null && command.canExecute()) {
viewer.getEditDomain().getCommandStack().execute(command);
}
}
Now what happens is that editpart will be requested for creation, so the action itself doesn't know how the command works, what makes it objective agaist the command.
So to make things work, you need to install new EditPolicy to your EditPart. EditPolicies can be installed on EditParts createDefaultEditPolicies() function. This EditPolicy must react and return command when there is CreateRequest. This way any child can provide own kind of command for creating children for itself.
Here is a good image how it works (controller is EditPart):
Please ask if I can help you some more. I know that this looks bit more complex, but this makes your own life much more easier, and after you have done that, you actually understand Command-Request Pattern quite well, and it can be reused in many different places.

Categories

Resources