Headers fragment item listener - android-tv

I'm trying to print out in console headers fragment item titles/id's on dpad movement using listener. What am I doing wrong and is there maybe an alternative to accomplish my goal?
For instance:
Would print out "Category 3" or "...." id.
public class XFragment extends BrowseFragment {
//onCreate()
setOnItemViewSelectedListener(new OnItemViewSelectedListener() {
#Override
public void onItemSelected(Presenter.ViewHolder itemViewHolder,
Object item, RowPresenter.ViewHolder rowViewHolder, Row row) {
Log.d("TAG", "Here!");
}
});
}
I can't even "catch" the selection between header items.

Found a solution myself. Turns out, it was quite easy.
if (getHeadersFragment() != null){
getHeadersFragment().setOnHeaderViewSelectedListener(new HeadersFragment.OnHeaderViewSelectedListener() {
#Override
public void onHeaderSelected(RowHeaderPresenter.ViewHolder viewHolder, Row row) {
// catch your item by row.getId();
}
});
}

Related

javaFX focusHandler?

I am just changing from AWT to JavaFX and im wondering how to work with focus.
For Exampe: In AWT I wrote something like that:
Button bFocus = new Button("Focus");
bFocus.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
System.out.println("Having the Focus");
}
public void focusLost(FocusEvent e) {
System.out.println("Lost the Focus");
}
});
But how does it work in JavaFX? I tried many different things, but that doesnt work...
JavaFX has an API that defines observable properties with which you can register listeners and respond when they change. Almost all state that belongs to UI elements in JavaFX is represented by these properties, allowing you to register a listener that responds when they change.
So, for example, the superclass of all UI elements, Node has a ReadOnlyBooleanProperty called focused, with which you can register a listener:
Button bFocus = new Button("Focus");
bFocus.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
if (isNowFocused) {
System.out.println("Having the Focus");
} else {
System.out.println("Lost the Focus");
}
});
I thought it might be helpful to see an example which specifies the ChangeListener as an anonymous inner class like James_D mention here.
TextField yourTextField = new TextField();
yourTextField.focusedProperty().addListener(new ChangeListener<Boolean>()
{
#Override
public void changed(ObservableValue<? extends Boolean> arg0, Boolean oldPropertyValue, Boolean newPropertyValue)
{
if (newPropertyValue)
{
System.out.println("Textfield on focus");
}
else
{
System.out.println("Textfield out focus");
}
}
});
I hope this answer is helpful!

How to make always visible headers of rows in RowsFragment

Here is what i have now.
Simply my RowsFragment is look like this,
public static class SampleFragmentB extends RowsFragment {
private final ArrayObjectAdapter mRowsAdapter;
public SampleFragmentB() {
mRowsAdapter = new ArrayObjectAdapter(new ShadowRowPresenterSelector());
setAdapter(mRowsAdapter);
setOnItemViewClickedListener(new OnItemViewClickedListener() {
#Override
public void onItemClicked(
Presenter.ViewHolder itemViewHolder,
Object item,
RowPresenter.ViewHolder rowViewHolder,
Row row) {
Toast.makeText(getActivity(), "Implement click handler", Toast.LENGTH_SHORT)
.show();
}
});
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
createRows();
getMainFragmentAdapter().getFragmentHost().notifyDataReady(getMainFragmentAdapter());
}
private void createRows() {
String json = Utils.inputStreamToString(getResources().openRawResource(
R.raw.page_row_example));
CardRow[] rows = new Gson().fromJson(json, CardRow[].class);
for (CardRow row : rows) {
mRowsAdapter.add(createCardRow(row));
}
}
private Row createCardRow(CardRow cardRow) {
PresenterSelector presenterSelector = new CardPresenterSelector(getActivity());
ArrayObjectAdapter adapter = new ArrayObjectAdapter(presenterSelector);
for (Card card : cardRow.getCards()) {
adapter.add(card);
}
HeaderItem headerItem = new HeaderItem(cardRow.getTitle());
return new CardListRow(headerItem, adapter, cardRow);
}
}
This is what i exactly want to do,
So I want to make always visible Header of each row without selecting into or focusing into RowsFragment. I'am using leanback v24 to add multiple rows into each header item.
You might want to check the Sofa library for Android TV that extends the Leanback library capabilities by offering a set of more powerful features. In BrowseSupportFragment, mRowsFragment.setExpand should be true. Additional reference: how to always show headers in RowsFragment

javafx CheckBoxTreeItem update parents programmatically

I have to retrieve some data from my database to dynamically create a TreeView and select some CheckBoxTreeItems from this TreeView. This TreeView represents permissions to a menu structure.
My doubt is when I create the TreeView and select specific items from the Tree according to the user's permissions programmatically, the parents items don't have any status change (selected or indeterminate). But when I select any item directly from the interface, the parents get updated.
For example, here I have my screen when I select the items programmatically:
You can see that I have two menu items selected, but the parents aren't.
On this image, I have selected the same menu items using the screen, and the parents were updated with indeterminate status or selected if I select all children inside the submenu.
I have gone through the documentation, google and here on Stack Overflow, but only found examples to update the children.
Is there a way to update the parents programmatically or to call the event executed from the screen when an item is selected?
EDIT:
All items from the Tree have the independent property set to false.
I came with a workaround for this problem.
I had to first create all the TreeView structure, and change the selected property after using this code snippet:
Platform.runLater(new Runnable() {
#Override
public void run() {
selectItems();
}
});
Here is the code to verify the TreeItems:
private void selectItems(){
TreeItem root = tree.getRoot();
if (root != null) {
selectChildren(root);
}
}
private void selectChildren(TreeItem<TesteVO> root){
for(TreeItem<TesteVO> child: root.getChildren()){
// HERE I CHECK IF THE USER HAS PERMISSION FOR THE MENU ITEM
// IF SO, I CHANGE THE SELECTED PROPERTY TO TRUE
if (child.getValue().id == 4) {
((CheckBoxTreeItem) child).setSelected(true);
}
// IF THERE ARE CHILD NODES, KEEP DIGGING RECURSIVELY
if(!child.getChildren().isEmpty()) {
selectChildren(child);
}
}
}
If there is a simpler way, please let me know!
This is not the case. Parent items do get automatically get set to the indeterminate state when you select a child item. I'm not sure if this is something that got corrected from the time that this question was posted, probably not.
My guess is that there's a programming bug in how the node was selected or how the TableView was constructed and initialized.
Here's some code that shows what I'm doing, and it works! In my case, I'm using a CheckBoxTreeItem<File> for the TreeItem.
How the treeview was created
treeView = new TreeView(root);
treeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
#Override
public void changed(ObservableValue observableValue, Object o, Object t1) {
CheckBoxTreeItem<File> node = (CheckBoxTreeItem<File>)t1;
if (node.getValue() != currentFile) {
setFileDetail(node);
showChildren(node);
}
}
});
treeView.setCellFactory(new CallBackWrapper());
treeView.setShowRoot(false);
Below show the CallBackWrapper class.
private class CallBackWrapper implements Callback<TreeView<File>, TreeCell<File>> {
Callback<TreeView<File>, TreeCell<File>> theCallback;
private CallBackWrapper() {
theCallback = CheckBoxTreeCell.<File>forTreeView(getSelectedProperty, converter);
}
#Override
public TreeCell<File> call(TreeView<File> fileTreeView) {
return theCallback.call(fileTreeView);
}
final Callback<TreeItem<File>, ObservableValue<Boolean>> getSelectedProperty = (TreeItem<File> item) -> {
if (item instanceof CheckBoxTreeItem<?>) {
return ((CheckBoxTreeItem<?>) item).selectedProperty();
}
return null;
};
final StringConverter<TreeItem<File>> converter = new StringConverter<TreeItem<File>>() {
#Override
public String toString(TreeItem<File> object) {
File item = object.getValue();
return fileSystemView.getSystemDisplayName(item);
}
#Override
public TreeItem<File> fromString(String string) {
return new TreeItem<File>(new File(string));
}
};
}
And lastly here some code that the selection was made in:
boolean selectNode(CheckBoxTreeItem<File> parentNode, String name) {
Object[] children = parentNode.getChildren().toArray();
for (Object child : children) {
CheckBoxTreeItem<File> childItem = (CheckBoxTreeItem<File>) child;
if (name.equals(childItem.getValue().getName())) {
childItem.setSelected(true);
//treeView.getSelectionModel().select(child); <-- this does not work!
return true;
}
}
return false;
}

Eclipse Scout Neon value in cell changed

I have table field with editable column. When I change value in one cell I need to calculate value in other fields.
I would like to know, how to detect when value in cell has change.
I couldn't find any hooks that will tell me that value in cell has change.
I found :
#Override
public void fireTableEventInternal(final TableEvent e) {
if (e.getType() == TableEvent.TYPE_ROWS_UPDATED) {
AbstractProductsTableField.this.execPriceValueChange();
} else {
super.fireTableEventInternal(e);
}
}
but I don't think this is a way to go.
I think that execCompleteEdit is the function you need.
#Order(10)
public class MyColumn extends AbstractStringColumn {
#Override
protected String getConfiguredHeaderText() {
return "MyColumn";
}
#Override
protected void execCompleteEdit(ITableRow row, IFormField editingField) {
//Test if there is a new value:
//compare getValue(row) and ((IStringField) editingField).getValue()
//Call super to store the value to the cell (default behavior):
super.execCompleteEdit(row, editingField);
}
}

expand TreeView (parent)nodes which contains selected item

I have a TreeView existing out of User objects. The TreeView represents the hierarchy of the Users:
Master1
Super1
Super2
User1
User2
Super3
User3
Super4
Master2
...
Every TreeItem is Collapsed when the TreeView is initialized. However, it can be that when the FXML is loaded, a TreeItem object is passed through from another FXML file. Eg: User3 has been passed through:
selectedUserTreeItem = (TreeItem<User>) currentNavigation.getPassthroughObject(); //this is the User3 TreeItem
I try to use a recursive function to expand all the parent nodes from the selecterUserTreeItem
if (selectedUserTreeItem != null) {
expandTreeView(selectedUserTreeItem);
}
tvUsers.setRoot(rootItem);
This is what I have so far:
private void expandTreeView(TreeItem<User> selectedItem) {
if (selectedItem != null) {
System.out.println(selectedItem);
if (selectedItem.isLeaf() == false) {
selectedItem.setExpanded(true);
}
TreeItem<User> parent = selectedItem.getParent();
expandTreeView(parent);
} else {
System.out.println("null");
}
}
I think it has to do something with the fact that the function is a void function and it should be returning a TreeItem object I suppose but for some reason I don't succeed in doing it.
Could someone point me in the right direction?
Ok, I notice that in your expandTreeView() method you expand the node and then you recurse to the previous node to expand that. In my own code I expanded from the root to the leaf, so lets try that:
private static <T> void expandTreeView(TreeItem<T> selectedItem) {
if (selectedItem != null) {
expandTreeView(selectedItem.getParent());
if (!selectedItem.isLeaf()) {
selectedItem.setExpanded(true);
}
}
}
No I don't think its because your method is returning void.
Try setting your TreeView root first before expanding:
>>> tvUsers.setRoot(rootItem);
if (selectedUserTreeItem != null) {
expandTreeView(selectedUserTreeItem);
}
If that doesn't work then try wrapping your initial expandTreeView() to run later:
Platform.runlater( new Runnable()
{
public void run() { expandTreeView( selectedUserTreeItem ); }
};
Ok, I had the same problem and found that I had to delay the expansion a bit like this:
Platform.runlater( new Task<Void>()
{
#Override
protected Void call() throws Exception
{
Thread.sleep( 250 );
return null;
}
#Override
protected void succeeded()
{
expandTreeView( selectedUserTreeItem );
}
} );
You may have to try and vary the delay to get it to work in your case.

Resources