Gluon Afterburner Presenter.initialize() not called - gluon-mobile

Link to repository: https://gitlab.com/RichardGladman/medimindr
I've created a new Multiple view with Afterburner project using the IntelliJ plugin and added a new view to the project. It displays some about information as I thought it would be easy. The view displays just fine with the exception that the AboutPresenter doesn't get initialised meaning the AppBar is not populated.
The presenter class
package com.thefifthcontinent.medimindr.views;
... imports snipped ...
public class AboutPresenter extends GluonPresenter<MediMindr> {
#FXML
private View about;
public void initialize() {
about.showingProperty().addListener((obs, oldValue, newValue) -> {
if (newValue) {
AppBar appBar = getApp().getAppBar();
appBar.setNavIcon(MaterialDesignIcon.MENU.button(e ->
getApp().getDrawer().open()));
appBar.setTitleText("About");
}
});
}
}
The creation in the AppViewManager
public static final AppView ABOUT_VIEW = view(
bundle.getString("drawer.about"),
AboutPresenter.class,
MaterialDesignIcon.DASHBOARD,
SHOW_IN_DRAWER);
I can't see a difference between what I have done and what was created with the project.

It turns out they are still configured in the pom.xml. I thought it would be auto injection using Afterburner.

Related

Initialize method not getting called on GoBackAsync, Xamarin forms

The question can be really basic since I have little to no knowledge about Xamarin Forms.
I have recently started working on an old Xamarin Forms project where I had to upgrade "Prism.Plugin.Popups" plugin to Version="7.2.0.1046"
and “Prism.Unity.Forms" to Version="7.2.0.1422"
I had to Implement IInitialize Interface since INavigatingAware is deprecated in latest Prism framework as mentioned in https://github.com/PrismLibrary/Prism/issues/1858
Issue:
I want app to navigate back from XPopupPage to AViewModel with the code _navigationService.GoBackAsync(navParams); which is working but Initialize function of AViewModel isn’t getting called once it comes back from XPopupPage.
Here’s the code:
AViewModel:
public class AViewModel : BindableBase, INavigationAware, IInitialize {
....
// Code to navigate to XPopupPageViewModel private void ShowPopup(object obj)
{
_navigation.NavigateAsync($”{.....}”);
}
//NOT GETTING CALLED once it come back from XPopupPageViewModel
public void Initialize(INavigationParameters parameters) {
.....
} }
XPopupPageViewModel:
public class XPopupPageViewModel : BindableBase, INavigationAware, IInitialize
{
//Code to navigate back to AViewModel private void Update(object obj)
{
....
var navParams = new NavigationParameters(.....); _navigationService.GoBackAsync(navParams);
} }
From the github issue you posted:
Use OnNavigatedTo when calling GoBack

the best practice to integrate arFragment (sceneForm) with existing Fragment APP

We have been working on adding AR features to our existing APP for a couple of months with limited progress. Very excited to read the recent development from google on sceneForm and arFragment. our current APP consists three Fragments and one of them will need AR features.
It looks straight forward to us,so We replaced the Fragment in our APP with arFragment. The build is successful and stopped during running with little information for debugging. any suggestion on the proper steps for us to upgrade from Fragment to arFragment? or maybe I missed the points of arFragment here?
in order to show the problem without for you to go through our length code (yet valuable to us), we constructed a dummy project based on the sample project from Google: HelloSceneform. Basically, we changed the static Fragment to dynamic Fragment. Only two files are changed and two files are added, which are attached thereafter. The modified project can be built successfully, but stopped when starting to run.
Thank you
Peter
/////// File modified, HelloSceneformActivity.java:
import android.support.v4.app.FragmentTransaction;
// private ArFragment arFragment;
private ItemOneFragment arFragment;
//arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.ux_fragment);
arFragment = ItemOneFragment.newInstance();
//Manually displaying the first fragment - one time only
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout, arFragment);
transaction.commit();
/////// File modified, activity_ux.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".HelloSceneformActivity">
</FrameLayout>
////// File added fragment_item_one.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/frame_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ItemOneFragment">
</FrameLayout>
/////// File added, ItemOneragment.java:
package com.google.ar.sceneform.samples.hellosceneform;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.ar.sceneform.ux.ArFragment;
public class ItemOneFragment extends ArFragment {
public static ItemOneFragment newInstance() {
ItemOneFragment fragment = new ItemOneFragment();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_item_one, container, false);
}
}
I have experienced the same when I try to add the ArFragment dynamically to my activity.
It is crashing because I was trying to access the ArSceneView right after I commit the fragment which appeared to be null at that point.
The solution that worked for me was to implement a completion listener that will provide a callback in the Activity when the fragment is done configuring the ARSession.
Below is the basic idea.
public class MyActivity implements MyArFragment.OnCompletionListener{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportFragmentManager().beginTransaction().add(R.id.fragment_holder, new
MyArFragment(), "my_arfragment").commit();
}
#Override
public void onComplete() {
ArFragment arFragment = (ArFragment) getSupportFragmentManager().findFragmentByTag("my_arfragment");
ArSceneView view = arFragment.getArSceneView();
Scene scene = view.getScene();
scene.addOnUpdateListener(this::onUpdateFrame);
}
}
And the fragment:
public class MyFragment extends ArFragment{
public static interface OnCompleteListener {
public abstract void onComplete();
}
private OnCompleteListener mListener;
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
this.mListener = (OnCompleteListener)context;
}
catch (final ClassCastException e) {
throw new ClassCastException(context.toString() + " must implement
OnCompleteListener");
}
}
#Override
protected Config getSessionConfiguration(Session session) {
//Update session config...
mListener.onComplete();
return config;
}
}
In one of my project I've used the following structure to accomplish the integration of ArFragment. Maybe this will give you some new hints.
I have a root layout with the first element that is a FrameLayout called "body".
This "body" is used as a placeholder to switch the 3 Fragment that exist into the app.
One of these 3 is called "SimulationFragment" and extends ArFragment of Sceneform.
The corresponding layout is composed by the root FrameLayout with some elements and another nested FrameLayout called "ar_frameLayout".
At Runtime I've changed the implementation of onCreateView for the SimulationFragment with a direct call of super.onCreateView() that gives me the base view of ArFragment (this call initializes also the scene from getArSceneView().getScene()).
After that I've added this view into the container view of the simulation fragment that I've previously inflated and then returned it.
Something like this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View containerView = inflater.inflate(R.layout.fragment_simulation, container, false);
FrameLayout arCoreFrameLayout = containerView.findViewById(R.id.ar_core_frame_layout);
// Inflate the layout for this fragment
View view = super.onCreateView(inflater, container, savedInstanceState);
arCoreFrameLayout.addView(view);
return containerView;
}
ItemOneFragment extends ArFragment but overrides its onCreateView method to inflate its own layout file. I think that's the problem. ArFragment can't find its ArSceneView and other code elements and will just not work.
I really liked the solution of #kdroider, but he forgot to remove reference to activity in onDetach(), which might be quite important. Also, rewote the code in Kotlin:
import android.content.Context
import com.google.ar.core.Config
import com.google.ar.core.Session
import com.google.ar.sceneform.ux.ArFragment
class AsyncArFragment : ArFragment() {
private var onArReadyListener: OnArReadyListener? = null
interface OnArReadyListener {
fun onArReady()
}
override fun getSessionConfiguration(session: Session): Config {
onArReadyListener?.onArReady()
return super.getSessionConfiguration(session)
}
override fun onAttach(context: Context) {
super.onAttach(context)
try {
onArReadyListener = context as OnArReadyListener
} catch (e: ClassCastException) {
throw ClassCastException(context.toString() + " must implement OnArReadyListener")
}
}
override fun onDetach() {
super.onDetach()
onArReadyListener = null
}
}
And don't forget to implement OnArReadyListener interface.
WARNING. Replacing fragments with transaction
AnotherFragment -> AsyncArFragment works okay
AsyncArFragment -> AnotherFragment -> AsyncArFragment doesn't work for some reason (onResume() and then immediately onDestroy() are called). If you know how to fix it, please write in comments.
For anyone coming here through google (like me):
Depending on your use case it might not be necessary to override the ArFragment - simply make sure to access the scene after arFragment.setOnSessionInitializationListener is called.

Navigate to Specflow step from within Step Definitions

So I have a few tests where i've reused steps from within steps.
But i'm now having a nightmare on the maintenance front, in that I cant easily navigate between the steps.
Here's an example:
[Given(#"I have an order")]
public void GivenIHaveAnOrder()
{
Given("an open store");
Given("I am an existing customer");
Given("I am on homepage");
When("I search for a component");
When("I add the component to my basket");
}
How do I navigate to one of those internal steps?
If I wanted to navigate to the "When("I search for a component");" step I cant.
If I were on the feature file I could simply right click the step and "go to definition" but I cant do that here. Does anyone have a solution?
I assume that you are calling the steps with the Given/When- functions, because they are in a different binding class. Am I right?
There is a better way of doing it, than using this functions.
Did you had a look at the driver concept and context injection?
Have a look here: http://www.specflow.org/documentation/Context-Injection/
Simply extract your logic of your steps to a driver class and get an instance from it in the different step classes:
class Driver
{
public void AnOpenStore()
{
...
}
}
[Binding]
public class StepClass1
{
private Driver _driver;
public StepClass1(Driver driver)
{
_driver = driver;
}
[Given(#"I have an order")]
public void IHaveAnOrder()
{
_driver.AnOpenStore();
}
}
[Binding]
public class StepClass2
{
private Driver _driver;
public StepClass2(Driver driver)
{
_driver = driver;
}
[Given(#"an open store")]
public void AnOpenStore()
{
_driver.AnOpenStore();
}
}
When you arrange your step implementations like that, the reusing of other steps is much more easier.

Call WebView page method from referenced WinRT Component with AllowForWeb class

I have a XAML page with WebView inside (for example MainPage.xaml). Also I have WinRT Component with class marked with [AllowForWeb] attribute. This component is referenced from project where MainPage.xaml located and in code-behind AddWebAllowedObject method is used. And I can't reference main project back because of circular dependency.
How to call MainPage.xaml.cs methods from component class? Very usual situation. Is there are some standard way to do it?
For example. I have a method inside RT component that could be called from JavaScript
public void ShowMessage(string message)
{
// I want to call here function from MainPage.xaml.cs
}
How to call MainPage.xaml.cs methods from component class? Very usual situation. Is there are some standard way to do it?
Yes, you can pass the method from MainPage.xaml.cs to Windows Runtime Component through delegate(Currently it's very limited to use delegate in Runtime Component using C#, see this case, so I use C++ as demo).
For Runtime Component Class MyClass.h:
public delegate Platform::String^ MyFunc(int a, int b);
public ref class MyClass sealed
{
public:
MyClass();
static Platform::String^ MyMethod(MyFunc^ func)
{
Platform::String^ abc=func(4, 5);
return abc;
}
};
And you can use the delegate in code behind like below:
using MyComponentCpp;
private void myBtn_Click(object sender, RoutedEventArgs e)
{
String abc=MyClass.MyMethod(MyMethod);
myTb.Text = abc;
}
private String MyMethod(int a, int b)
{
return (a.ToString() + b.ToString());//replace this line with your own logic.
}
And here is the complete Demo: TestProject.
Thankfully to #Elvis Xia who has gived me idea, I has found a solution how to do it without C++.
I have create a third project as Class Library. It doesn't has restrictions to use Action. This library I have referenced from main project and from WinRT component. Code of class inside library:
public class BridgeClass
{
public static event Action<string> MessageReceived;
public static void Broadcast(string message)
{
if (MessageReceived != null) MessageReceived(message);
}
}
Code inside main project with webview is:
// place somewhere
BridgeClass.MessageReceived += ShowMessage;
// ....... and add a method
void ShowMessage(string msg)
{
}
And now i can call this code from WinRT component:
public void ShowMessage(string message)
{
BridgeClass.Broadcast("lalala");
}

Get active Window in UI

I'm using a Vaadin-UI with a servlet like this:
#WebServlet(value = "/*", asyncSupported = true)
#VaadinServletConfiguration(productionMode = false, ui = MyUI.class, widgetset = "widgetsets.MyWidgetSet")
public class MyServlet extends VaadinServlet {
}
#Theme("mytheme")
#PreserveOnRefresh
#Push
public class MyUI extends UI {
#Override
protected void init(VaadinRequest request) {
Navigator navigator = new Navigator(this, this);
navigator.addView("myView", MyView.class);
// add some other views
navigator.navigateTo("myView");
setNavigator(navigator);
}
}
public class MyView extends VerticalLayout implements View {
#Override
public void enter(ViewChangeListener.ViewChangeEvent event) {
// init UI stuff
}
}
It works fine so far but what I want to do now, is to use the ConfirmDialog Add-on from inside my view. My problem is that all of the ConfirmDialog.show() methods require a Window as a parameter. How can I obtain the active Window object isnide View or UI classes? UI.getCurrent().getWindows() is empty and all the examples I found use an Application class.
Version 1 of the addon uses an existing window (create one and pass it, as Vaadin only has Page and UI by default, a Window is just an component). With version 2 of the addon you pass only the UI, where the dialog (which subclasses Window) will show itself.

Resources