Multilevel Master/Detail Databinding with EMF and RCP - data-binding

I made a model with EMF, representing the settings of a device, and a RCP GUI. In the GUI I have a list to select different devices of the type of the model (Master).
The model has a List of Objects of a small class which should be displayed in a table (Detail).
The tableItems itself need to be edited so I have a small GUI part with checkboxes etc. to change the settings. Here the tableitem is master and all fields shown in the GUI are details.
Observable for the List of devices:
IObservableValue selection = ViewersObservables.observeSingleSelection(availableDevicesList);
Table:
IObservableList list = EMFObservables.observeDetailList(Realm.getDefault(), selection,DevicePackage.Literals.LIST);
TableViewer tableViewer = new TableViewer(parent, SWT.SINGLE | SWT.FULL_SELECTION);
tableViewer.setInput(list);
IObservableValue tableSelection = ViewersObservables.observeSingleSelection(tableViewer);
Editing:
Spinner field1 = new Spinner(parent, SWT.BORDER);
dbc.bindValue(SWTObservables.observeSelection(field1), EMFObservables.observeDetailValue(Realm.getDefault(), tableSelection, DevicePackage.Literals.Value1));
When changing the device selection the tableitems get replaced. But the tableSelection seems to have a problem with this. Sometimes it still contains values of a a tableitem from a different device and sometimes it just contains null.
I also have a button which gets enabled/disabled according the validation status of all fields. When the tableSelection puts null into these fields the validation does not work and the button is disabled until a entry in the table is selected.
I tried to manually set the selection empty with a listener on the list and:
tableViewer.setSelection(StructuredSelection.EMPTY, true);
but this does not do the full job. At least all "old" values are replaced but the null problem still occurs.
All I need is to set the tableSelection to an empty state as after the launch of the application, when no tableitem was selected yet.

I found the solution by myself. The problem was actually the spinner itself. It threw a nullpointer when the selection was empty and there was no value.
I solved it by giving it a custom converter (from int to int...) where I return a default value if the source is null.
Now the validation works fine and my button's enable state is set correct.

Related

JavaFX Observable where the value can be swapped

I am writing a small experimental desktop application. Basically it has the options to display a list of recipes and detailed information about a single recipe.
To accomplish that i implemented a class called RecipeContext that stores a ObservableList<Recipe> that i bind to a TableView, so the view gets automatically updated if i add to, or remove from the collection.
I want something similar for the single recipe, an Observable where i simply have to change the contained recipe and have the view automatically update to display the new recipe information.
To make this a bit more clear, i want something like this:
SingleObservable<Recipe> detailedRecipe = new SingleObservable<>(new Recipe("A"));
detailedInformationController.bindRecipeObservable(detailedRecipe);
// Recipe A is displayed
detailedRecipe.set(new Recipe("B"));
// View is notified about the change and displays Recipe B
Is there a class that does that?
SimpleObjectProperty will do what you want.
SimpleObjectProperty<Recipe> detailedRecipe = new SimpleObjectProperty<>(new Recipe("A"));
...
detailedRecipe.set(new Recipe("B"));
http://docs.oracle.com/javase/8/javafx/api/javafx/beans/property/SimpleObjectProperty.html

CodeName One about lists

I have a problem I want to use the list and when I click on a component of the list it take me to another form (make an action) meaning if I click on an item from the list depending on the selected index it takes me to another form.
Is this in a GUI builder app or manual app?
For GUI builder use the action event callback for the list see: http://www.codenameone.com/how-do-i---handle-eventsnavigation-in-the-gui-builder--populate-the-form-from-code.html
Then get the index/selected item using:
int index = list.getSelectedIndex();
Object value = list.getSelectedItem();
Then you can show the form you want using:
showForm("FormName", null);
In handcoded apps you can get the selected item/index in exactly the same way then do something like:
form.show();
To show a specific form.

Displaying TableView when MKAnnotation(Pin) in MKMapView touched/pressed/clicked

I want to display quite a bit of demographic data for a certain pin when someone touches on it, so providing a pop-up isn't going to cut it. I figured once the pin is touched I will just stick a tableviewController onto the NavigationController and the table view will have access to the object and display the single objects information, with one item per row and 1 section.
Anyway I'm having a hard time figuring out MKMapViewDelegates methods as it appears none of them do what I need and/or allow me to return a tableview or push that view onto the navigation controller.
I played around with:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation;
But that requires a MKAnnotationView be returned and I really just need this method to work by showing the user a table view of all the data. I was hoping for something simple like a userDidTouchPin method....
Anyone have any ideas how to accomplish what I am trying to do?
If you want to do something when the user selects the pin (and not a button on its callout), then implement the mapView:didSelectAnnotationView: delegate method and present or push your detail view controller there.
The selected annotation object is available as the annotation property of the view parameter:
- (void)mapView:(MKMapView *)mapView
didSelectAnnotationView:(MKAnnotationView *)view
{
YourDetailViewController *dvc = [[YourDetailViewController alloc] init...
dvc.annotation = view.annotation;
//present or push here
[dvc release];
}
You might need to check which type of annotation was selected (eg. if MKUserLocation was selected do nothing, etc) and you might need to cast the view.annotation to your own annotation class to easily access any custom properties you may have.

How to bind background of a column in silverlight during runtime?

I have a grid with bunch of columns in it. To start with this grid is build during run time in the code behind and not much code in XAML except the generic grid, so I can't bind the column background during design time. I have been reading various blogs, questions and found the following as the closest answer.
SolidColorBrush backgroundBrush = new SolidColorBrush();
Binding b = new Binding("BackGroundColor");
b.Converter = new ColorConverterForReadOnly(); //This converter return color based on parameter
b.ConverterParameter = data;
BindingOperations.SetBinding(backgroundBrush, SolidColorBrush.ColorProperty, b);
column.Background = backgroundBrush;
When I ran the code, the binding did not happen, I put a break point (in the first line) inside the converter to see if debug hits the converter at all and it did not hit the converter at all. If I would put
column.Background = new SolidColorBrush(Colors.Blue)
I can see the the column colors set to blue.
What am I missing in the binding that is not letting converter invoked?
Thanks,
The binding is targeting a "BackGroundColor" property. For the binding to be hit, the DataContext of the column control would need to be an object that has a "BackGroundColor" property.

PyQt (or just QT). How to get QComboBox to fire a signal whenever it is set to a value (even if unchanged)

I am using PyQt4, but this is general enough that it could just apply to QT.
I have a series of QComboBoxes that I fill from left to right (i.e. selecting an item in the leftmost will populate the next one. Selecting an item in that one will populate the next, and so on)
I am having difficulty getting my signals to fire under all situations (i.e. regardless of whether the current index changes or not AND regardless of whether the item is set by the user or set programatically).
More detail:
I rely on the signals of the first QCombox to fire whenever an item is selected so that I can populate the next QCombobox in the gui. I then rely on THAT QCombobox to emit a signal so that I can populate the next one. And so on.
I want to pre-select an item in each QCombobox based on the user's last interaction with the gui.
I have a unique function per QCombobox that is responsible for populating and pre-selecting just that QCombobox. The code looks something like this:
comboBox1.blockSignals(True)
comboBox1.clear()
comboBox1.addItems(sorted(itemList))
comboBox1.blockSignals(False)
comboBox1.setCurrentIndex(intLastSavedState1)
where intLastSavedState1 is an integer that is derived from the text that was last selected by the user the last time they had used the app. I had hoped that the last line of this function would fire a signal that would cause the next combo box's function to load and pre-select an item (comboBox2). And that action would then cause the next comboBox's function to activate and it would cascade to the next and the next. But it is not working across all cases.
I have tried two versions of the signals:
self.connect(comboBox1, QtCore.SIGNAL("currentIndexChanged(const QString&)"), self.load_comboBox2)
and
self.connect(comboBox1, QtCore.SIGNAL("activated(const QString&)"), self.load_comboBox2)
In the first case, the signal will fire only if the intLastSavedState1 is different than whatever is currently selected in the combo box. This causes an issue if the user had last selected item 0 from that list. In this case QT does not recognize my script setting the the current index to 0 as being a change (since after loading the box it appears to think it is already on index 0), and so the signal does not fire.
In the second case, the signal will fire regardless of what is currently selected in the combo box... but only if activated by the user. It will not fire when my script tries to set the current index programatically.
These appear to be my only two options regarding the signals. So... is there another way of pre-selecting items in a QCombobox that will trigger a signal each and every time?
Well... sometimes just the act of asking a question can lead you to a (partial) answer.
I have a work-around but I am still interested in hearing if someone has a better idea.
I am now programatically setting the index of the QCombobox to -1 immediately after loading it up. Then, when I programatically set the actual index based on the user's history, it will always be considered a change (i.e. it will never be -1) and the signal will fire
using: currentIndexChanged(const QString&)
So my code looks like this now:
comboBox1.blockSignals(True)
comboBox1.clear()
comboBox1.addItems(sorted(itemList))
comboBox1.setCurrentIndex(-1)
comboBox1.blockSignals(False)
comboBox1.setCurrentIndex(intLastSavedState1)
and my signal looks like this:
self.connect(comboBox1, QtCore.SIGNAL("currentIndexChanged(const QString&)"), self.load_comboBox2)
This functions... does anyone have a better idea?
Thanks agian.
You can check current Index of your ComboBox and then either call your slot or do call setCurrentIndex().
Example:
if comboBox1.currentIndex() == index:
self.load_comboBox2(index)
else
comboBox1.setCurrentIndex(index)
This way you will not end up calling slot twice.

Resources