nested tab gwtp - google-app-engine

I posted a question the other day and didn't get much response. I have tried a few things but still no luck. I am trying to nest a tab presenter in GWTP. I have one frame (North) that is tab group 1 and one frame (West) that is tab group 2. When I interact with group 1 I update the nested tab presenter which controls group 2. I have looked at the example for nested tab presenters but I have been unable to determine my error from it.
The two TabContainerPresenters are ManagementTabsPresenter and SettingsTabsPresenter. The children of these are like the HomePresenter below. The content for these children is displayed in the center of a DockLayoutPanel located in the MainPreseter. I want the ManagementTabsPresenter and the SettingsTabsPresenter to be displayed in the West slot of the same DockLayoutPanel.
When I run this code everything is placed on the screen in the correct locations. You can even click the tabs and have actions occur. The problems start in that the SettingsPresenter is displayed first even though the default page is the HomePresenter. It's like it tries to reveal both at the same time on start up. Then when you selected any of the tabs which are part of the ManagementTabsPresenter or the SettingsTabsPresenter It opens the correct content in the MainPresenter.Center_Slot but the incorrect presenter is displayed in the MainPresenter.West_Slot. I can't figure out what's going wrong here. Any help would be appreciated.
Here is the code:
public class HomePresenter extends Presenter<HomePresenter.MyView, HomePresenter.MyProxy> {
#Inject
AppPlaceManager appPlaceManager;
#NameToken(NameTokens.homePage)
#ProxyStandard
#NoGatekeeper
public interface MyProxy extends TabContentProxyPlace<HomePresenter> {
}
public interface MyView extends View {
}
#TabInfo(container = ManagementTabsPresenter.class)
static TabData getTabLabel(MainAppGinjector injector) {
return new TabDataBasic("home", 0);
}
#Inject
public HomePresenter(final EventBus eventBus, final MyView view, final MyProxy proxy) {
super(eventBus, view, proxy);
}
#Override
protected void revealInParent() {
RevealContentEvent.fire(this, ManagementTabsPresenter.TYPE_MAIN_CONTENT_SLOT, this);
}
}
public class ManagementTabsPresenter extends TabContainerPresenter<ManagementTabsPresenter.MyView, ManagementTabsPresenter.MyProxy> {
/**
* {#link ManagementTabsPresenter}'s proxy.
*/
#ProxyStandard
public interface MyProxy extends NonLeafTabContentProxy<ManagementTabsPresenter> {
}
/**
* {#link ManagementTabsPresenter}'s view.
*/
public interface MyView extends TabView {
}
/**
* Use this in leaf presenters, inside their {#link #revealInParent} method.
*/
#ContentSlot
public static final GwtEvent.Type<RevealContentHandler<?>> TYPE_MAIN_CONTENT_SLOT = MainPresenter.CENTER_SLOT;
/**
* This will be the event sent to our "unknown" child presenters, in order for
* them to register their tabs.
*/
#RequestTabs
public static final Type<RequestTabsHandler> TYPE_Management_RequestTabs = new Type<RequestTabsHandler>();
#TabInfo(container = HeaderTabsPresenter.class, nameToken = NameTokens.homePage)
static TabData getTabLabel(MainAppGinjector injector) {
return new TabDataBasic("Management", 0);
}
#Inject
public ManagementTabsPresenter(final EventBus eventBus, final MyView view,
final MyProxy proxy, AppPlaceManager appPlaceManager) {
super(eventBus, view, proxy,TYPE_MAIN_CONTENT_SLOT, TYPE_Management_RequestTabs);
}
#Override
protected void revealInParent() {
RevealContentEvent.fire(this, HeaderTabsPresenter.TYPE_VERTICAL_TABS_SLOT, this);
}
}
public class SettingsTabsPresenter extends TabContainerPresenter<SettingsTabsPresenter.MyView, SettingsTabsPresenter.MyProxy> {
/**
* {#link SettingsTabsPresenter}'s proxy.
*/
#ProxyStandard
public interface MyProxy extends NonLeafTabContentProxy<SettingsTabsPresenter> {
}
/**
* {#link SettingsTabsPresenter}'s view.
*/
public interface MyView extends TabView {
}
#TabInfo(container = HeaderTabsPresenter.class, nameToken = NameTokens.appUserCollectionPage)
static TabData getTabLabel(MainAppGinjector injector) {
return new TabDataBasic("Settings", 1);
}
/**
* Use this in leaf presenters, inside their {#link #revealInParent} method.
*/
#ContentSlot
public static final GwtEvent.Type<RevealContentHandler<?>> TYPE_MAIN_CONTENT_SLOT = MainPresenter.CENTER_SLOT;
/**
* This will be the event sent to our "unknown" child presenters, in order for
* them to register their tabs.
*/
#RequestTabs
public static final Type<RequestTabsHandler> TYPE_Settings_RequestTabs = new Type<RequestTabsHandler>();
#Inject
public SettingsTabsPresenter(final EventBus eventBus, final MyView view,
final MyProxy proxy, AppPlaceManager appPlaceManager) {
super(eventBus, view, proxy,TYPE_MAIN_CONTENT_SLOT, TYPE_Settings_RequestTabs);
}
#Override
protected void revealInParent() {
RevealContentEvent.fire(this, HeaderTabsPresenter.TYPE_VERTICAL_TABS_SLOT, this);
}
}
public class HeaderTabsPresenter extends TabContainerPresenter<HeaderTabsPresenter.MyView, HeaderTabsPresenter.MyProxy> {
#Inject EventBus eventBus;
/**
* {#link HeaderTabsPresenter}'s proxy.
*/
#ProxyStandard
public interface MyProxy extends Proxy<HeaderTabsPresenter> {
}
/**
* {#link HeaderTabsPresenter}'s view.
*/
public interface MyView extends TabView {
void changeTab(Tab tab, TabData tabData, String historyToken);
}
/**
* This will be the event sent to our "unknown" child presenters, in order for
* them to register their tabs.
*/
#RequestTabs
public static final Type<RequestTabsHandler> TYPE_HEADER_RequestTabs = new Type<RequestTabsHandler>();
/**
* Fired by child proxie's when their tab content is changed.
*/
#ChangeTab
public static final Type<ChangeTabHandler> TYPE_HEADER_ChangeTab = new Type<ChangeTabHandler>();
#ContentSlot
public static final Type<RevealContentHandler<?>> TYPE_VERTICAL_TABS_SLOT = MainPresenter.WEST_SLOT;
#Inject
public HeaderTabsPresenter(final EventBus eventBus, final MyView view,
final MyProxy proxy) {
super(eventBus, view, proxy, TYPE_VERTICAL_TABS_SLOT, TYPE_HEADER_RequestTabs, TYPE_HEADER_ChangeTab);
}
#Override
protected void revealInParent() {
RevealContentEvent.fire(this, MainPresenter.NORTH_SLOT, this);
}
}
public class MainPresenter extends Presenter<MainPresenter.MyView, MainPresenter.MyProxy>{
#Inject VSMRequestFactory requestFactory;
#Inject VSMMessages vsmMessages;
#Inject VSMExceptionMessages vsmExceptionMessages;
#Inject EventBus eventBus;
#ProxyStandard
#NoGatekeeper
public interface MyProxy extends Proxy<MainPresenter> {
}
public interface MyView extends View {
}
#ContentSlot
public static final Type<RevealContentHandler<?>> SOUTH_SLOT = new Type<RevealContentHandler<?>>();
#ContentSlot
public static final Type<RevealContentHandler<?>> WEST_SLOT = new Type<RevealContentHandler<?>>();
#ContentSlot
public static final Type<RevealContentHandler<?>> CENTER_SLOT = new Type<RevealContentHandler<?>>();
#ContentSlot
public static final Type<RevealContentHandler<?>> NORTH_SLOT = new Type<RevealContentHandler<?>>();
#Inject
public MainPresenter(EventBus eventBus, MyView view, MyProxy proxy) {
super(eventBus, view, proxy);
}
#Override
protected void revealInParent() {
RevealRootLayoutContentEvent.fire(this, this);
}
#Override
protected void onReveal() {
super.onReveal();
initializeAppUser();
}
}

I stumbled upon something similar before... I think it is because both of them inherit from TabContainerPresenter and that there is a bug in gwtp that calls onReveal() on the wrong inherited child.
take a look at this gwtp forum post:
https://groups.google.com/forum/?fromgroups#!searchin/gwt-platform/gilad$20egozi/gwt-platform/p0s3BlN-ceE/5EL3nynaiu4J
Is that the case? if so, I don't think anyone filed a bug on the gwtp issue tracker, so let me know.
(of-course, the best check is not to inherit and see if its working)

Related

JavaFX 8: Checkbox in TableView and Add-on into to selected Item?

I would like to create a payroll program such that when the user tick a CheckBox in TableView, the name (String) will be carried on to the panel on the right and with TextFields to enter more info such as this:
I tried to follow the MVC hierarchy thus far as I code:
PayrollMainApp.java
public class PayrollMainApp extends Application {
private Stage primaryStage;
private BorderPane rootLayout;
private ObservableList<Employee> selectEmployeeTable = FXCollections.observableArrayList();
public PayrollMainApp(){
selectEmployeeTable.add(new Employee(false,"Hans Muster"));
selectEmployeeTable.add(new Employee(true,"Ruth Mueller"));
selectEmployeeTable.add(new Employee(false,"Heinz Kurz"));
selectEmployeeTable.add(new Employee(false,"Cornelia Meier"));
selectEmployeeTable.add(new Employee(false,"Werner Meyer"));
selectEmployeeTable.add(new Employee(false,"Lydia Kunz"));
selectEmployeeTable.add(new Employee(false,"Anna Best"));
selectEmployeeTable.add(new Employee(false,"Stefan Meier"));
selectEmployeeTable.add(new Employee(false,"Martin Mueller"));
}
public ObservableList<Employee> getSelectEmployeeTable(){
return selectEmployeeTable;
}
#Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle("PayrollApp");
initRootLayout();
showEmployeeOverview();
}
/**
* Initializes the root layout.
*/
public void initRootLayout() {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(PayrollMainApp.class.getResource("view/RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Shows the person overview inside the root layout.
*/
public void showEmployeeOverview() {
try {
// Load person overview.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(PayrollMainApp.class.getResource("view/EmployeeOverview.fxml"));
AnchorPane personOverview = (AnchorPane) loader.load();
// Set person overview into the center of root layout.
rootLayout.setCenter(personOverview);
// Give the controller access to the main app
EmployeeOverviewController controller = loader.getController();
controller.setMainApp(this);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Returns the main stage.
* #return
*/
public Stage getPrimaryStage() {
return primaryStage;
}
public static void main(String[] args) {
launch(args);
}
}
Employee.java
public class Employee {
private BooleanProperty checkedBox = new SimpleBooleanProperty(false);
private StringProperty employeeName = new SimpleStringProperty();
public Employee(){
super();
}
public Employee(boolean checkedBox, String employeeName){
this.checkedBox = new SimpleBooleanProperty(false);
this.employeeName = new SimpleStringProperty(employeeName);
}
public BooleanProperty checkedBoxProperty(){
return this.checkedBox;
}
public StringProperty employeeNameProperty(){
return this.employeeName;
}
public java.lang.Boolean getSelectBox() {
return this.checkedBoxProperty().get();
}
public StringProperty getEmployeeName() {
return employeeName;
}
public void setSelectBox(final java.lang.Boolean checkedBox){
this.checkedBoxProperty().set(checkedBox);
}
public void setEmployeeName(StringProperty employeeName) {
this.employeeName = employeeName;
}
}
EmployeeOverviewController.java
public class EmployeeOverviewController {
#FXML
private TableView<Employee> selectEmployeeTable;
#FXML
private TableColumn<Employee, String> employeeNameColumn;
#FXML
private TableColumn<Employee, Boolean> checkBoxColumn;
private PayrollMainApp mainApp;
public EmployeeOverviewController() {
}
#FXML
public void initialize() {
checkBoxColumn.setCellValueFactory(cellData -> cellData.getValue().checkedBoxProperty());
checkBoxColumn.setCellFactory(param -> new CheckBoxTableCell<Employee, Boolean>());
employeeNameColumn.setCellValueFactory(cellData -> cellData.getValue().employeeNameProperty());
}
public void setMainApp(PayrollMainApp mainApp){
this.mainApp = mainApp;
//Add observable list data to the table
selectEmployeeTable.setItems(mainApp.getSelectEmployeeTable());
}
}
And a util class to make the checkBox visible in the table:
SelectBoxCellFactory.java
public class SelectBoxCellFactory implements Callback {
#Override
public TableCell call(Object param) {
CheckBoxTableCell<Employee,Boolean> checkBoxCell = new CheckBoxTableCell();
return checkBoxCell;
}
}
Here is my output thus far:
I know this has a table in it as compared to the previous output. Honestly I'm still indecisive as to use which, because I think using TextFields would make it look better. But all I hope for now is that this design is not impossible to code...
I really hope you can help me... Thank you for your help in advance.
It's probably easiest to use a TableView for the right panel. You can create a FilteredList from your original list:
FilteredList<Employee> selectedEmployees
= new FilteredList<>(selectEmployeeTable, Employee::getSelectBox);
and then use that for your second table.
If you prefer to use text fields (in what looks like a GridPane?) you can still use the filtered list above, but you will need to register a listener with it and update the layout "by hand" when items are added and removed.

testng how to dynamically set groups from Factory?

Before I setup a test class like the code below:
1. the Factory and test Dataprovider both used excel as the dataprovider.
2. In the Factory dataprovider table, it has a list of url
3. Each time, it will find one of the url in the factory dataprovider table, and run the test in each test methods..
public class Test {
WebDriver driver;
private String hostName;
private String url;
#Factory(dataProvider = "xxxx global variables", dataProviderClass = xxxx.class)
public GetVariables(String hostName, String url) {
this.hostName = hostName;
this.url = url;
}
#BeforeMethod
#Parameters("browser")
public void start(String browser) throws Exception {
driver = new FirefoxDriver();
driver.get(url);
Thread.sleep(1000);
}
#Test(priority = 10, dataProvider = "dataprovider Test A", dataProviderClass = xxx.class)
public void TestA(Variable1,
Variable2,Variable3) throws Exception {
some test here...
}
#Test(priority = 20, dataProvider = "dataprovider Test B", dataProviderClass = xxx.class)
public void TestB(Variable1,
Variable2,Variable3)
throws Exception {
some test here...
}
#AfterMethod
public void tearDown() {
driver.quit();
}
Now I want to dynamically assign different group for each test for different url. I am thinking add a variable 'flag' in the #Factory dataprovider:
#Factory(dataProvider = "xxxx global variables", dataProviderClass = xxxx.class)
public GetVariables(String hostName, String url, String flag) {
this.hostName = hostName;
this.url = url;
this.flag = flag;
}
That when flag.equals("A"), it will only run test cases in test groups={"A"}.
When flag.equals("B"), it will only run test cases in test groups ={"B"},
When flag.equals("A,B"), it will only run test cases in test groups ={"A","B"}
Is there any way I can do that?
Thank you!
TestNG groups provides "flexibility in how you partition your tests" but it isn't for conditional test sets. For that you simply use plain old Java.
You can use inheritance or composition (I recommend the latter, see Item 16: Favor composition over inheritance from Effective Java).
Either way the general idea is the same: use a Factory to create your test class instances dynamically creating the appropriate class type with the appropriate test annotations and/or methods that you want to run.
Examples:
Inheritance
import org.testng.annotations.Factory;
import org.testng.annotations.Test;
public class DemoTest {
#Factory
public static Object[] createTests() {
return new Object[]{
new FlavorATest(),
new FlavorBTest(),
new FlavorABTest()
};
}
/**
* Base test class with code for both A-tests and B-tests.
*
* Note that none of these test methods are annotated as tests so that
* subclasses may pick which ones to annotate.
*/
public static abstract class BaseTest {
protected void testA() {
// test something specific to flavor A
}
protected void testB() {
// test something specific to flavor B
}
}
// extend base but only annotate A-tests
public static class FlavorATest extends BaseTest {
#Test
#Override
public void testA() {
super.testA();
}
}
// extend base but only annotate B-tests
public static class FlavorBTest extends BaseTest {
#Test
#Override
public void testB() {
super.testB();
}
}
// extend base and annotate both A-tests and B-tests
public static class FlavorABTest extends BaseTest {
#Test
#Override
public void testA() {
super.testA();
}
#Test
#Override
public void testB() {
super.testB();
}
}
}
Composition
import org.testng.annotations.Factory;
import org.testng.annotations.Test;
public class DemoTest {
#Factory
public static Object[] createTests() {
return new Object[]{
new FlavorATest(),
new FlavorBTest(),
new FlavorABTest()
};
}
private static void testA() {
// test something specific to flavor A
}
private static void testB() {
// test something specific to flavor B
}
// only create A-test methods and delegate to shared code above
public static class FlavorATest {
#Test
public void testA() {
DemoTest.testA();
}
}
// only create B-test methods and delegate to shared code above
public static class FlavorBTest {
#Test
public void testB() {
DemoTest.testB();
}
}
// create A-test and B-test methods and delegate to shared code above
public static class FlavorABTest {
#Test
public void testA() {
DemoTest.testA();
}
#Test
public void testB() {
DemoTest.testB();
}
}
}
Your factory methods won't be as simple as you'll need to use your "flag" from your test data to switch off of and create instances of the appropriate test classes.

Using GWT-Editor in a UiBinder

I am trying to make use of Editor in a GWT application, so I have read the official documentation. I have also looked at he question enter link description here and its answers, but I still cannot figure out the ultimate "purpose" of Editors. As an example case, supposing a UiBinder with some fields:
#UiField
TextBox name;
#UiField
TextArea comment;
#UiField
ListBox type;
...
I create additionally a method editCustomer as:
private void editCustomer(CustomerProxy entity) {
MyRequestFactory requestFactory = MyRequest.getRequestFactory();
CustomerRequestContext requestContext = requestFactory.customerRequest();
entity = requestContext.edit(entity);
editorDriver.edit(entity, requestContext);
}
I think the approach with Editor makes for connecting UiBinder fields with the Database. How is this done, based on the common way of sending data in the database through a "Save" Buttton?
#UiHandler("saveButton")
void onSaveButtonClick(ClickEvent event){
????
}
I have been using the MVP pattern for a while and have some more complicated editors. I found that it is good put put your EditorDriver in your view becuase when you initialize it you can bind it to your specific view. My examples require an activity / view interface / view implementation.
This is an abstract activity that can be extended by other activities but I included the relevant content. I have stripped quite a bit of code out but this should give you an idea of a useful way to use editors. My editor is quite complex and has quite a few sub editors. I have only included the name and description. We have found this to be a quite useful design pattern for handling Editors.
public abstract class AbstractTaskBuilderActivity extends <E extends AnalyticsTaskProxy, R extends DaoRequest<E>> implements TaskBuilderView {
/**
* Create a new task. This will initialize any new lists.
* #param context The RequestContext to use to create the task.
* #param clazz The class type to be created.
* #return
*/
protected E create(R context, Class<E> clazz) {
// This is implemented in my inherited classes.
E editableAnalyticsTask = context.create(clazz);
// More initialization code expecially initializing arrays to empty so that
// any ListEditor sub editors will work.
return editableAnalyticsTask;
}
/**
* Call to edit the task and update the dashboards.
* #param context
* #param task
*/
protected void doEdit(R context, E task) {
RequestFactoryEditorDriver<? super AnalyticsTaskProxy, ?> driver = display.getEditorDriver();
E editable = context.edit(task);
context.save(editable).with(driver.getPaths()).to(new Receiver<Long>() {
#Override
public void onFailure(ServerFailure error) {
display.showError(error.getMessage());
super.onFailure(error);
}
public void onConstraintViolation(Set<ConstraintViolation<?>> violations) {
display.getEditorDriver().setConstraintViolations(violations);
}
#Override
public void onSuccess(Long response) {
clientFactory.getPlaceController().goTo(getSavePlace());
}
});
driver.edit(editable, context);
}
/**
* Save the task.
*/
#Override
public void onSaveTask() {
RequestFactoryEditorDriver<? super AnalyticsTaskProxy, ?> driver = display.getEditorDriver();
RequestContext request = driver.flush();
request.fire();
}
}
My view interface
public interface TaskBuilderView extends View {
public interface Presenter {
void onSaveTask();
}
public RequestFactoryEditorDriver<AnalyticsTaskProxy, ?> getFactoryEditorDriver();
public void setPresenter(Presenter presenter);
}
My view implementation
public class AnalyticsTaskBuilderViewImpl extends ViewImpl implements AnalyticsTaskBuilderView, Editor<AnalyticsTaskProxy> {
interface AnalyticsTaskBuilderDriver extends RequestFactoryEditorDriver<AnalyticsTaskProxy, AnalyticsTaskBuilderViewImpl> {
}
/**
* UiBinder implementation.
*
* #author chinshaw
*
*/
#UiTemplate("AnalyticsTaskBuilderView.ui.xml")
interface Binder extends UiBinder<Widget, AnalyticsTaskBuilderViewImpl> {
}
/**
* Name component for the name of the analytics operation.
* This also implements {#link HasEditorErrors so it can show
* constraint violations when an error occurs.
*/
#UiField
ValueBoxEditorDecorator<String> name;
/**
* Description component that edits analytics operation description.
* This also implements {#link HasEditorErrors} so it can show
* constraint violations when an error occurs
*/
#UiField
ValueBoxEditorDecorator<String> description;
public AnalyticsTaskBuilderViewImpl(Resources resources) {
super(resources);
// Must initialize the view before calling driver initialize
initWidget(GWT.<Binder> create(Binder.class).createAndBindUi(this));
driver.initialize(this);
}
#Override
public void setPresenter(Presenter presenter) {
this.presenter = presenter;
bindToPresenter();
}
// Save the task
#UiHandler("saveTask")
void handleClick(ClickEvent clickEvent) {
presenter.onSaveTask();
}
#Override
public RequestFactoryEditorDriver<AnalyticsTaskProxy, ?> getEditorDriver() {
return driver;
}
}

GWTP nested tab presenter

I am trying to nest a tab presenter in GWTP. I have one frame (North) that is tab group 1 and one frame (West) that is tab group 2. When I interact with group 1 I update the nested tab presenter which controls group 2. I have looked at the example for nested tab presenters but I have been unable to determine my error from it.
The two TabContainerPresenters are ManagmentTabsPresenter and SettingsTabsPresenter. The children of these are like the HomePresenter below. The content for these children is displayed in the center of a DockLayoutPanel. I want the ManagementTabsPresenter and the SettingsTabsPresenter to be displayed in the West slot of the same DockLayoutPanel.
The problem as I see it is that when this code is run the revealInParent() method of the ManagementTabsPresenter and the revealInParent() method of the SettingsTabsPresenter are both called whenever I try to view one on the child tabs. (i.e. homePresenter). Why are both of these revealInParent methods called? What am I missing? It is true that both SettingsTabsPresenter and ManagementTabsPresenter are in a parent tab that gets revealed. Does this mean that the revealInParent of both of these tabcontainerprestners(nonleavetabcontentproxy) will be called when the parent tabcontainerpreseter is revelatedinparent?
public class HomePresenter extends Presenter<HomePresenter.MyView, HomePresenter.MyProxy> {
#Inject
AppPlaceManager appPlaceManager;
#NameToken(NameTokens.homePage)
#ProxyStandard
#NoGatekeeper
public interface MyProxy extends TabContentProxyPlace<HomePresenter> {
}
public interface MyView extends View {
}
#TabInfo(container = ManagementTabsPresenter.class)
static TabData getTabLabel(MainAppGinjector injector) {
return new TabDataBasic(injector.getVSMMessages().home_tab(), ClientConstants.HOME_TAB_POSITION);
}
#Inject
public HomePresenter(final EventBus eventBus, final MyView view, final MyProxy proxy) {
super(eventBus, view, proxy);
}
#Override
protected void revealInParent() {
RevealContentEvent.fire(this, ManagementTabsPresenter.TYPE_MAIN_CONTENT_SLOT, this);
}
}
public class ManagementTabsPresenter extends TabContainerPresenter<ManagementTabsPresenter.MyView, ManagementTabsPresenter.MyProxy> {
/**
* {#link ManagementTabsPresenter}'s proxy.
*/
#ProxyStandard
public interface MyProxy extends Proxy<ManagementTabsPresenter> {
}
/**
* {#link ManagementTabsPresenter}'s view.
*/
public interface MyView extends TabView {
}
/**
* Fired by child proxie's when their tab content is changed.
*/
#ChangeTab
public static final Type<ChangeTabHandler> TYPE_Management_ChangeTab = new Type<ChangeTabHandler>();
/**
* Use this in leaf presenters, inside their {#link #revealInParent} method.
*/
#ContentSlot
public static final GwtEvent.Type<RevealContentHandler<?>> TYPE_MAIN_CONTENT_SLOT = MainPresenter.CENTER_SLOT;
/**
* This will be the event sent to our "unknown" child presenters, in order for
* them to register their tabs.
*/
#RequestTabs
public static final Type<RequestTabsHandler> TYPE_Management_RequestTabs = new Type<RequestTabsHandler>();
#Inject
public ManagementTabsPresenter(final EventBus eventBus, final MyView view,
final MyProxy proxy, AppPlaceManager appPlaceManager) {
super(eventBus, view, proxy,TYPE_MAIN_CONTENT_SLOT, TYPE_Management_RequestTabs, TYPE_Management_ChangeTab);
}
#Override
protected void revealInParent() {
RevealContentEvent.fire(this, MainPresenter.WEST_SLOT, this);
}
}
public class SettingsTabsPresenter extends TabContainerPresenter<SettingsTabsPresenter.MyView, SettingsTabsPresenter.MyProxy> {
/**
* {#link SettingsTabsPresenter}'s proxy.
*/
#ProxyStandard
public interface MyProxy extends Proxy<SettingsTabsPresenter> {
}
/**
* {#link SettingsTabsPresenter}'s view.
*/
public interface MyView extends TabView {
}
/**
* Fired by child proxie's when their tab content is changed.
*/
#ChangeTab
public static final Type<ChangeTabHandler> TYPE_Settings_ChangeTab = new Type<ChangeTabHandler>();
/**
* Use this in leaf presenters, inside their {#link #revealInParent} method.
*/
#ContentSlot
public static final GwtEvent.Type<RevealContentHandler<?>> TYPE_MAIN_CONTENT_SLOT = MainPresenter.CENTER_SLOT;
/**
* This will be the event sent to our "unknown" child presenters, in order for
* them to register their tabs.
*/
#RequestTabs
public static final Type<RequestTabsHandler> TYPE_Settings_RequestTabs = new Type<RequestTabsHandler>();
#Inject
public ManagementTabsPresenter(final EventBus eventBus, final MyView view,
final MyProxy proxy, AppPlaceManager appPlaceManager) {
super(eventBus, view, proxy,TYPE_MAIN_CONTENT_SLOT, TYPE_Settings_RequestTabs, TYPE_Settings_ChangeTab);
}
#Override
protected void revealInParent() {
RevealContentEvent.fire(this, MainPresenter.WEST_SLOT, this);
}
}
public class MainPresenter extends Presenter<MainPresenter.MyView, MainPresenter.MyProxy>{
#Inject VSMRequestFactory requestFactory;
#Inject VSMMessages vsmMessages;
#Inject VSMExceptionMessages vsmExceptionMessages;
#Inject EventBus eventBus;
#ProxyStandard
#NoGatekeeper
public interface MyProxy extends Proxy<MainPresenter> {
}
public interface MyView extends View {
}
#ContentSlot
public static final Type<RevealContentHandler<?>> SOUTH_SLOT = new Type<RevealContentHandler<?>>();
#ContentSlot
public static final Type<RevealContentHandler<?>> WEST_SLOT = new Type<RevealContentHandler<?>>();
#ContentSlot
public static final Type<RevealContentHandler<?>> CENTER_SLOT = new Type<RevealContentHandler<?>>();
#ContentSlot
public static final Type<RevealContentHandler<?>> NORTH_SLOT = new Type<RevealContentHandler<?>>();
#Inject
public MainPresenter(EventBus eventBus, MyView view, MyProxy proxy) {
super(eventBus, view, proxy);
}
#Override
protected void revealInParent() {
RevealRootLayoutContentEvent.fire(this, this);
}
#Override
protected void onReveal() {
super.onReveal();
initializeAppUser();
}
}
It should be an event issue, when you select a tab, SelectionEvent may be consumed by the wrong tab. Could you add some code about tab initialization?

How to close dialog window from viewmodel (Caliburn+WPF)?

I haveViewModel1 and View1 associated with it. I start dialog window from ViewModel2 (some another viewmodel) using IWindowManager object. The code from ViewModel2 class:
windowManager.ShowDialog(new ViewModel());
So, I have Dialog Window with View1 user control.
My answer is next - I can close that dialog window using red close button, but how to close it using my specific button (contained in View1 user control), something like "Cancel" button with close command (Command={Binding CancelCommand}), CancelCommand of course is contained in ViewModel1 class.
It's even easier if your view model extends Caliburn.Micro.Screen:
TryClose();
You can get the current view (in your case the dialog window) with implementing the IViewAware interface on your ViewModel. Then you can call Close on the the view (the Window created as the dialog) when your command is executed.
The easiest why is to derive from ViewAware:
public class DialogViewModel : ViewAware
{
public void ExecuteCancelCommand()
{
(GetView() as Window).Close();
}
}
If you are not allowed to derive you can implement it yourself:
public class DialogViewModel : IViewAware
{
public void ExecuteCancelCommand()
{
dialogWindow.Close();
}
private Window dialogWindow;
public void AttachView(object view, object context = null)
{
dialogWindow = view as Window;
if (ViewAttached != null)
ViewAttached(this,
new ViewAttachedEventArgs(){Context = context, View = view});
}
public object GetView(object context = null)
{
return dialogWindow;
}
public event EventHandler<ViewAttachedEventArgs> ViewAttached;
}
Note: I've used Caliburn.Micro 1.3.1 for my sample.
A cleaner way (Subject of personal taste) that I use alot is to use the IResult pattern, this way you abstract the Window implemenation
Viewmodel
public IEnumerable<IResult> CloseMe()
{
yield return new CloseResult();
}
Result code
public class CloseResult : Result
{
public override void Execute(ActionExecutionContext context)
{
var window = Window.GetWindow(context.View);
window.Close();
base.Execute(context);
}
}
public abstract class Result : IResult
{
public virtual void Execute(ActionExecutionContext context)
{
OnCompleted(this, new ResultCompletionEventArgs());
}
protected virtual void OnCompleted(object sender, ResultCompletionEventArgs e)
{
if (Completed != null)
Completed(sender, e);
}
public event EventHandler<ResultCompletionEventArgs> Completed;
}
edit (Only needed for IoC): If you wanna take it a step further you do a base class for all screens
public abstract class ShellPresentationModel : Screen
{
public ShellPresentationModel(IResultFactory resultFactory)
{
Result = resultFactory;
}
public IResultFactory Result { get; private set; }
}
This way you can inject dependencies with a IoC much easier, then your VIewmodel close method will look like this
public IEnumerable<IResult> CloseMe()
{
yield return Result.Close();
}
An example on a IResult that uses dependency can be
public class ShowDialogResult<TModel> : Result
{
private readonly IWindowManager windowManager;
private readonly TModel model;
private Action<TModel> configure;
public ShowDialogResult(IWindowManager windowManager, TModel model)
{
this.windowManager = windowManager;
this.model = model;
}
public IResult Configure(Action<TModel> configure)
{
this.configure = configure;
return this;
}
public override void Execute(ActionExecutionContext context)
{
if(configure != null)
configure(model);
windowManager.ShowDialog(model);
base.Execute(context);
}
}
edit Just noticed that i forgot to add an example of the above IoC exmaple, here goes
With a child IoC container pattern it would look like this
public IEnumerable<IResult> ShowDialog()
{
yield return Result.ShowDialog<MyViewModel>();
}
Without a child container pattern you would need to inject parent dependeync into the child manually
yield return Result.ShowDialog<MyViewModel>().Configure(m => m.SomeData = this.SomeData);

Resources