GWT: formfactor dependent editor - gwt

I'm developing a web app for different formfactors. Each has its own client factory to create formfactor dependent views. Everythings works fine so far but I'm stuck when it comes to the Editor Framework.
To make use of the framework I have to declare a marker interface like so:
interface Driver extends SimpleBeanEditorDriver<User, UserEditor> {}
Since this happens in my formfactor agnostic activity I want the type UserEditor to refer to the actual implementation based on the formfactor, i.e. UserEditorPhone, UserEditorTablet, UserEditorYouNameIt.
To no avail I tried using deferred binding in module.gwt.xml:
<replace-with class="com.example.client.desktop.UserEditorDesktop">
<when-type-is class="com.example.client.view.UserEditor"/>
</replace-with>
Any ideas on what I'm missing and how to avoid having a one-to-one-relationship between formfactors and UserEditor-activities?

You'll want your formfactor-agnostic activity to only know about SimpleBeanEditorDriver<User, ?>, and move the Driver interface into each one of UserEditorDesktop, UserEditorTable and UserEditorPhone.
The activity will then ask a formfact-dependent object (e.g. its view, if you use MVP and the activity is the presenter) for an instance of the editor driver rather than using GWT.create() directly.
(I can give code sample if you detail how your code is organized: are you using MVP? is the editor your view? how's it instantiated? etc.)

Related

Prism 6 and constructor calling

Based from a video from Brian Lagunas (YouTube Link) I started using Prism 6. I am a little bit confused, where the constructor of the MainWindowViewModel is getting called. I nearly copied his project and can't find the part. If i set a break point in the constructor, it never gets there.
Was he no showing something in the video or something?
If you have a look at the code for this presentation, you can see that Brian is using Prism's attached dependency property to couple view and viewmodel through the ViewModelLocator.
prism:ViewModelLocator.AutoWireViewModel="True"
In the video around 33:00 he gives the full explanation how this ViewModelLocator works: first it builds the viewmodel name out of the view's name through convention. Then it either resolves this name to a type through an IoC container or reflection. IoC is pretty straight forward: give a type or name and it will give you an instance. For the reflection part (when you run without a container), Prism uses the Activator type to create a new instance.
In the final code available on GitHub, Brian is using Unity as IoC container. Custom mappings for his sub-views (ViewA/ViewB) are made in the Bootstrapper. As there is no custom mapping for MainViewModel, following process happens:
The app starts with MainWindow as the startup window.
The attached property for the ViewModelLocator gets 'triggered', internal logic will map from MainWindow to MainWindowViewModel
As we're using Unity, the ViewModelLocator asks for an instance of the viewmodel
Unity will create a new MainWindowViewModel object and the constructor will get hit
So you won't see new xxxViewModel() in code, but it does get created. This means you have much greater flexibility over hardcoded object creation when it comes down to adding dependencies.

Catel Mvvm Plugins PropertyGrid

I would like to know. How I can dynamically choose view? I would like to make the PropertyGrid in my application. The PropertyGrid should must change when user selects object. As I understand for this task I have to use a DataTemplate but how I can dynamically create DataTemplate in code? The fact is that I use plug-ins and View and ViewModel for each plugin located in separate dll and so I can't directly write DataTemplate in PropertyesViewModel.
How can I make the edit properties for each plugin using the Propertygrid if I can't use a DataTemplate?
For Catel it doesn't matter in which assemblies the views / view models are located since it uses relative naming conventions. However, if you want to show a custom view based on logic that might reside inside a plugin, I think this is out of scope for Catel.
To solve this issue, you must implement a custom service that can communicate with the plugins and resolve the right view for a selected object. One solution might be naming conventions (if it's a PersonModel, you might want to show the PersonPropertiesView and PersonPropertiesViewModel). However, this must be a custom service.

Using mgwt for desktop and mobile applications

I have an application written in GWT. I want to be able to provide a subset of the same application for use when the site is opened in mobile browsers, and have been looking at mgwt as a way of achieving this.
The way I am expecting it to work is that I will augment my existing GWT application project with mgwt code (with some logic sharing) resulting in two entry points. My question is how to manage this given a single html page? I have seen the approach described in this article and was wondering whether that will work well with mgwt or whether there should be another pattern I should be considering?
I don't think you need 2 entry points. As kiran said above, you should reuse all the code except the view components. In case you used the GWT Activities and Places module, the view components should be completely decoupled from the rest of the code.
In this case you can use the the GWT.create method associated with the correct definitions in the module xml definition:
//in your entry point:
private IClientFactory clientFactory = GWT.create(IClientFactory.class);
//in your module xml definition:
<replace-with class="com.vv.xui.client.DesktopClientFactory">
<when-type-is class="com.vv.xui.client.IClientFactory" />
<when-property-is name="formfactor" value="desktop"/>
</replace-with>
<replace-with class="com.vv.xui.client.MobileClientFactory">
<when-type-is class="com.vv.xui.client.IClientFactory" />
<when-property-is name="formfactor" value="mobile"/>
</replace-with>
The form formfactor property can be defined as in this example:
https://code.google.com/p/gwt-cx/source/browse/trunk/gwtcx/gwtcx-core/gwtcx-core-client/src/main/resources/com/gwtcx/FormFactor.gwt.xml
In your IClientFactory you will have something like this:
public interface IClientFactory {
IHomeView getHomeView();
ISearchView getSearchView();
...
}
Where IHomeView and ISearchView are the view interfaces implemented by the desktop and the mobile versions. In my case the View implementations are UiBinder components that implement the associated view interface.
In your DesktopClientFactory you will have something like this:
public class DesktopClientFactory implements IClientFactory {
private static final ISearchView searchView = new com.vv.xui.client.view.desktop.SearchView.SearchView();
#Override
public ISearchView getSearchView() {
return searchView;
}
...
}
In this way you don't need different entry points for mobile and desktop and can share all the code except the view components.
That pattern in the link pointing to MobileWebApp on googlecode is correct. Basically you have UI view interfaces in GWT which stick to MVP pattern recommended on GWT. Then you can do different implementations of the UI Views based on the screen resolutions available. Obviously you don't want the same screen lay outs on desktop and mobile. So you will need to redesign your views for different form factors and then call the correct implementations based on the form factor the device. Since you already have a gwt application, you can create views for mobile using mgwt and reuse the code that you already created. But still you will have to create new views for mobile using mgwt, it wont be a straight forward replace.

How to Dynamically load EXTERNAL MVVM and NON MVVM controls using Caliburn Micro

I am loading controls dynamically from the web server from separate XAP files. After creating an instance I want to show them in tab Pages. The controls can be MMVM controls using CM but also non MVVM standard controls.
Before trying the tab I tested to simply show a control dynamically on the page by using:
<ContentControl Name="TestControl" />
Test control is a property of Type UserControl which is set via creating a new Instance of a dynamically loaded control. Now this gives me an error that it can't find the view. In case of non MVVM controls there is of course no view, so how do I load a non MVVM control?
I tried to make the test control a MVVM control, but still get the cannot load view error. Makes sense as such instance is not created. If I create an instance of the dynamically loaded view besides the view model, how do I "Add" this so that CM finds it?
Last but not least, how do I bind this to a tab control in Silverlight? The idea is to have a collection of user controls (plugins) which each is rendered in its separate tab page.
Thanks for any help.
(I got this done in no time NOT using MVVM, still not sure if MVVM is worth all the complexity)
There's no such thing as "mvvm control". MVVM is just a pattern not a control type. Basically, in Caliburn you don't need to work vith UserControls or Views directly, but if you pick the ViewModel first approach, Caliburn framework should be able to find the matching view for you. In your case since you're loading XAP files dynamically, you need to add them to the list of assemblies Caliburn looks to find a View/ViewModel (and bind them together) and this is done through IAssemblySource interface. According to the documentation here:
So, what is AssemblySoure.Instance? This is the place that
Caliburn.Micro looks for Views. You can add assemblies to this at any
time during your application to make them available to the framework,
but there is also a special place to do it in the Bootstrapper.

Adding Content to a GWT Horizontal Panel from another class

I am trying to populate the right-hand-side of a HorizontalPanel used in an onModuleLoad() method from another class (containing other widgets) so to keep the code separate.
What I am trying to achieve is similar to a PHP include where I can alter the code in another class and it will affect the right-hand panel only.
Does this other class have to be a composite widget? Or can I do a similar thing that I do when creating the Entry class?
I'm not sure if you mean you want to load a complete different GWT module on the right-hand panel or simply want to load a different class. I assume the latter.sense.
In such case a GWT TabPanel, but positioned Vertical. This is a combination of a DeckPanel and a TabBarPanel. In GWT there is standard VerticalTabPanel available, but you can find one in the open source cobogw library, see http://www.cobogw.org. An example including source code can be found on the demo page: http://cobogw.googlecode.com/svn/demo/WidgetsDemo.html#VerticalTabPanel
The example also uses a LazyPanel. This means each class is initialized only when the user clicks on the link, which makes startup a lot faster.
Just add the reference to the horizontalpanel to some other class (like a controller class or main panel class) and then call into this class from your right side panel. You can even have a controller class that holds this static horizontalpanel with a method like
HorizontalPanel hPanel; //set this from on module load, or controller.create method for instance
public static setRightContents(Panel panel){
hPanel.add(panel)
}
and just call this from the other class Controller.setRightContents(myNewRightPanel).
Really you just need to stop thinking this is a website and start thinking more of a thick client application using even driven programming.