JavaFx controlsFX AutoCompletionEvent doesn't work - events

I want to handle the AutoCompletionEvent of the controlsFX 8.0.5 framework, but somehow it will be never fired?! When no suggestions are available there should be one entry with "new..." and when this entry is chosen I want to do something. Therefore I set an EventHandler.
I implemented the binding like this:
AutoCompletionBinding<String> bind = TextFields.bindAutoCompletion(tf, sr -> {
List<String> shownSuggestions = new ArrayList<String>();
for (Client c : suggestions) {
if (!sr.getUserText().isEmpty()
&& c.toString().toLowerCase().startsWith(sr.getUserText().toLowerCase())) {
shownSuggestions.add(c.toString());
}
if (shownSuggestions.isEmpty()) {
if (sr.getUserText().isEmpty()) {
shownSuggestions.add(NEW_PARTY);
} else {
shownSuggestions.add(sr.getUserText() + NEW_PARTY_WITH_NAME);
}
}
}
return shownSuggestions;
});
And this is my EventHandler:
bind.setOnAutoCompleted(new EventHandler<AutoCompletionEvent<String>>() {
#Override
public void handle(AutoCompletionEvent<String> event) {
if (event.getCompletion().equals(NEW_PARTY)) {
System.out.println("new party chosen");
} else if (event.getCompletion().endsWith(NEW_PARTY_WITH_NAME)) {
System.out.println("new party with input chosen");
}
event.consume();
}
});
But there is no output on the console.
Can someone please help me? I'm trying this for days now...
regards

There is a bug in controlsFX 8.0.5 causing that the event never gets fired. So the code is correct, but it's never called.
Bug report in controlsFX 8.0.5

Related

i have integrate AutocompleteSupportFragment on map fagment .when im click on place search .app is crashed

i have integrate AutocompleteSupportFragment on map fagment .when im click on place search .app is crashed.its giving error.java.lang.NullPointerException: Place Fields must be set.
AutocompleteSupportFragment autocompleteFragment = (AutocompleteSupportFragment)
getChildFragmentManager().findFragmentById(R.id.autocomplete_frag);
if (autocompleteFragment != null) {
autocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ID, Place.Field.NAME));
}
if (autocompleteFragment != null) {
autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
#Override
public void onPlaceSelected(#NonNull Place place) {
// TODO: Get info about the selected place.
Toast.makeText(getContext(),place.getName(),Toast.LENGTH_SHORT).show();
}
#Override
public void onError(#NonNull Status status) {
// TODO: Handle the error.
Toast.makeText(getContext(),"Error",Toast.LENGTH_SHORT).show();
}
});
}
I had the same issue, and the Google developer Doc on this doesnt tell you the step you need to initialize Places (why would they include that...), but all you need to do is add the following snippet where you initialize the autoCompleteFragmentvariable.
if (!Places.isInitialized()) {
Places.initialize(getApplicationContext(), "YOUR_API_KEY);
}
Cheers

I wanted to make a separate method for listeners in the root view but it throws NPE

I have a borderpane as the root view and it was getting kind of big so I wanted to divide them into small chunks… with Views there is no problem, I can easily separate them into files and classes.
The problem I am having is that when I want to make a separate method for root view's listeners, it is throwing NPE.
This was my original code:
override val root = borderpane {
addClass(rootStyle)
paddingAll = 10.0
// listeners
setOnMouseEntered { scaleUp() }
setOnMouseExited { scaleDown() }
// end listeners
center {...}
}
}
This is my current code that throws NPE:
override val root = borderpane {
addClass(rootStyle)
paddingAll = 10.0
setListeners() // I added this
center {...}
}
}
private fun setListeners(){
with(root) {
setOnMouseEntered { scaleUp() }
setOnMouseExited { scaleDown() }
}
}
I tried it without with(root) but IDE highlighted them as errors.
I also tried to call the method in onBeforeShow(), it didn't throw any exceptions but listeners didn't work.
What is a proper way to handle this? In Android I easily make setListeners() method and call it from onCreate(). What would be an optimal equivalent of this in TornadoFX?
Edited:
I found a working code but still I am not sure if it is an optimal way... if you have better ways to handle this type of situations, feel free to add your answer.
Wheeee, it was right under my nose. I passed this (borderpane) into a method and it worked as expected.
override val root = borderpane{
setListeners(this)
}
private fun setListeners(borderPane: BorderPane) {
with(borderPane) {
setOnMouseEntered { scaleUp() }
setOnMouseExited { scaleDown() }
}
}

How to handle back button when at the starting destination of the navigation component

I've started working with the new navigation component and I'm really digging it! I do have one issue though - How am I supposed to handle the back button when I'm at the starting destination of the graph?
This is the code I'm using now:
findNavController(this, R.id.my_nav_host_fragment)
.navigateUp()
When I'm anywhere on my graph, it's working great, it send me back, but when I'm at the start of it - the app crashes since the backstack is empty.
This all makes sense to me, I'm just not sure how to handle it.
While I can check if the current fragment's ID is the same as the one that I know to be the root of the graph, I'm looking for a more elegant solution like some bool flag of wether or not the current location in the graph is the starting location or not.
Ideas?
I had a similar scenario where I wanted to finish the activity when I was at the start destination and do a regular 'navigateUp' when I was further down the navigation graph. I solved this through a simple extension function:
fun NavController.navigateUpOrFinish(activity: AppCompatActivity): Boolean {
return if (navigateUp()) {
true
} else {
activity.finish()
true
}
}
And then call it like:
override fun onSupportNavigateUp() =
findNavController(R.id.nav_fragment).navigateUpOrFinish(this)
However I was unable to use NavigationUI as this would hide the back arrow whenever I was at the start destination. So instead of:
NavigationUI.setupActionBarWithNavController(this, controller)
I manually controlled the home icon:
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_navigation_back)
Override onBackPressed in your activity and check if the current destination is the start destination or not.
Practically it looks like this:
#Override
public void onBackPressed() {
if (Navigation.findNavController(this,R.id.nav_host_fragment)
.getCurrentDestination().getId() == R.id.your_start_destination) {
// handle back button the way you want here
return;
}
super.onBackPressed();
}
You shouldn't override "onBackPressed", you should override "onSupportNavigateUp" and put there
findNavController(this, R.id.my_nav_host_fragment)
.navigateUp()
From the official documentation:
You will also overwrite AppCompatActivity.onSupportNavigateUp() and call NavController.navigateUp
https://developer.android.com/topic/libraries/architecture/navigation/navigation-implementing
In Jetpack Navigation Component, if you want to perform some operation when fragment is poped then you need to override following functions.
Add OnBackPressedCallback in fragment to run your special operation when back present in system navigation bar at bottom is pressed .
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
onBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
//perform your operation and call navigateUp
findNavController().navigateUp()
}
}
requireActivity().onBackPressedDispatcher.addCallback(onBackPressedCallback)
}
Add onOptionsItemMenu in fragment to handle back arrow press present at top left corner within the app.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setHasOptionsMenu(true)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) {
//perform your operation and call navigateUp
findNavController().navigateUp()
return true
}
return super.onOptionsItemSelected(item)
}
If there is no special code to be run when back is pressed on host fragment then use onSupportNavigateUp in Activity.
override fun onSupportNavigateUp(): Boolean {
if (navController.navigateUp() == false){
//navigateUp() returns false if there are no more fragments to pop
onBackPressed()
}
return navController.navigateUp()
}
Note that onSupportNavigateUp() is not called if the fragment contains onOptionsItemSelected()
As my back button works correctly, and using NavController.navigateUp() crashed on start destination back button. I have changed this code to something like this. Other possibility will be to just check if currentDestination == startDestination.id but I want to close Activity and go back to other Activity.
override fun onSupportNavigateUp() : Boolean {
//return findNavController(R.id.wizard_nav_host_fragment).navigateUp()
onBackPressed()
return true
}
/** in your activity **/
private boolean doubleBackToExitPressedOnce = false;
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
public void onBackPressed() {
int start = Navigation.findNavController(this, R.id.nav_host_fragment).getCurrentDestination().getId();
if (start == R.id.nav_home) {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(MainActivity.this, "Press back again to exits", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
} else {
super.onBackPressed();
}
}
If you mean the start of your "root" navigation graph (just incase you have nested navigation graphs) then you shouldn't be showing an up button at all, at least according to the navigation principles.
Just call this in your back button Onclick
requireActivity().finish()

Requesting Android permissions in a class (Xamarin)

I'm trying to request a permission at runtime for my app. I use a service provider to talk between the portable class and Android.
I start by calling this code on button press in the PCL:
using (new Busy(this))
{
var locationHelper = scope.Resolve<ILocationHelper>();
locationHelper.GetLocation(this);
}
This calls my Android level service:
public class AndroidLocationHelper : ILocationHelper, ILocationListener
{
readonly string[] PermissionsLocation =
{
Manifest.Permission.AccessCoarseLocation
};
const int RequestLocationId = 0;
public void GetLocation(SearchViewModel viewModel)
{
try
{
const string permission = Manifest.Permission.AccessCoarseLocation;
if (((int)Build.VERSION.SdkInt < 23) || (CheckSelfPermission(permission) == Permission.Granted))
{
}
else
RequestPermissions(PermissionsLocation, RequestLocationId);
}
catch (Exception ex)
{
Debug.WriteLine("Error while getting Location service");
Debug.WriteLine(ex.Message);
Messaging.AlertUser("There was an error with determining your location");
}
}
However, I get two errors on CheckSelfPermission and RequestPermissions. These two methods are only available to activities. The code works fine in MainActivity; however, I want to ask for permissions when the user hits a button, not in OnCreate or OnResume, etc.
Thanks for any help.
In your Android project, You can use this and use the Dependency Service to call it in Xamarin.Forms PCL project later:
var thisActivity = Forms.Context as Activity;
ActivityCompat.RequestPermissions(thisActivity, new string[] {
Manifest.Permission.AccessFineLocation }, 1);
ActivityCompat.RequestPermissions(thisActivity,
new String[] { Manifest.Permission.AccessFineLocation },
1);
You can try with ContextCompat.CheckSelfPermission, passing the application context, like this:
ContextCompat.CheckSelfPermission(Android.App.Application.Context, permission)
Update
In case of ActivityCompat.RequestPermissions, which requires an activity reference, you can keep track of the current activity. There is a very handy lib for that, called "CurrentActivityPlugin". You can find at https://github.com/jamesmontemagno/CurrentActivityPlugin
Rafael came up with a solution but I found another option that is a lot less effort just using MessagingCenter. In the MainActivity's OnCreate add a receiver that runs all the location code, that way you have access to all of the activities methods (and there are a bunch of tutorials on doing location services in MainActivity). Then add the Send inside of your service (the class).
To expound Rafael Steil's answer, I tried the suggested CurrentActivityPlugin and it worked on me. In my case I am trying to execute a voice call which needs CALL_PHONE permission. Here is the code snippet in your case: I used the ContextCompat & ActivityCompat so that I don't need to check the VERSION.SdkInt
using Plugin.CurrentActivity;
public void GetLocation(SearchViewModel viewModel){
var context = CrossCurrentActivity.Current.AppContext;
var activity = CrossCurrentActivity.Current.Activity;
int YOUR_ASSIGNED_REQUEST_CODE = 9;
if (ContextCompat.CheckSelfPermission(context, Manifest.Permission.AccessCoarseLocation) == (int)Android.Content.PM.Permission.Granted)
{
//Permission is granted, execute stuff
}
else
{
ActivityCompat.RequestPermissions(activity, new string[] { Manifest.Permission.AccessCoarseLocation }, YOUR_ASSIGNED_REQUEST_CODE);
}
}
It's dead simple
public bool CheckPermission()
{
const string permission = Manifest.Permission.ReceiveSms;
return ContextCompat.CheckSelfPermission(Forms.Context, permission) == (int) Permission.Granted;
}

JavaFX blocking native key event handling for treeview

I would like to change handling of key pressed events for example to do something else when user press up/down arrows but when i add eventHandler by setOnKeyPressed/setOnKeyReleased i cant stop native handling of those keys.
Example:
treeView.setOnKeyPressed(new EventHandler<KeyEvent>() {
private KeyCodeCombination prevNodeKeyCombination = new KeyCodeCombination(KeyCode.UP);
private KeyCodeCombination nextNodeKeyCombination = new KeyCodeCombination(KeyCode.DOWN);
public void handle(KeyEvent event)
{
if (prevNodeKeyCombination.match(event))
{
selectPrevSibling();
}
else if (nextNodeKeyCombination.match(event))
{
selectNextSibling();
}
event.consume(); // i try to block anything that goes by
}
});
Any idea how to override native key handling, if necessary i can try extend TreeView if that helps in something?
To override native handling of event use addEventFilter in my case it was:
treeView.addEventFilter(KeyEvent.ANY, new EventHandler<KeyEvent>() { ... }

Resources