diff --git a/de-lib/src/main/java/org/iplantc/de/apps/client/AppCategoriesView.java b/de-lib/src/main/java/org/iplantc/de/apps/client/AppCategoriesView.java index d9d66ad6a0..54bcb6411b 100644 --- a/de-lib/src/main/java/org/iplantc/de/apps/client/AppCategoriesView.java +++ b/de-lib/src/main/java/org/iplantc/de/apps/client/AppCategoriesView.java @@ -7,11 +7,11 @@ import org.iplantc.de.apps.client.events.selection.AppInfoSelectedEvent; import org.iplantc.de.apps.client.events.selection.CopyAppSelected; import org.iplantc.de.apps.client.events.selection.CopyWorkflowSelected; +import org.iplantc.de.apps.client.AppNavigationView; import org.iplantc.de.client.models.HasId; import org.iplantc.de.client.models.IsMaskable; import org.iplantc.de.client.models.apps.App; import org.iplantc.de.client.models.apps.AppCategory; -import org.iplantc.de.commons.client.widgets.DETabPanel; import com.google.gwt.user.client.ui.IsWidget; @@ -75,7 +75,7 @@ interface Presenter extends AppSearchResultLoadEvent.AppSearchResultLoadEventHan AppCategoriesView getWorkspaceView(); - void go(HasId selectedAppCategory, boolean selectDefaultCategory, DETabPanel tabPanel); + void go(HasId selectedAppCategory, boolean selectDefaultCategory, AppNavigationView appNavigationView); void setViewDebugId(String baseID); diff --git a/de-lib/src/main/java/org/iplantc/de/apps/client/AppNavigationView.java b/de-lib/src/main/java/org/iplantc/de/apps/client/AppNavigationView.java new file mode 100644 index 0000000000..ec940af299 --- /dev/null +++ b/de-lib/src/main/java/org/iplantc/de/apps/client/AppNavigationView.java @@ -0,0 +1,67 @@ +package org.iplantc.de.apps.client; + +import org.iplantc.de.client.models.IsMaskable; + +import com.google.gwt.event.logical.shared.HasSelectionHandlers; +import com.google.gwt.user.client.ui.IsWidget; +import com.google.gwt.user.client.ui.Widget; + +import java.util.List; + +/** + * A view in the Apps window for navigating groups of app categories or hierarchy roots + * This is effectively the same as TabPanel, except the tabs are replaced with a dropdown menu + * Adding a String + Widget to the view ties a dropdown selection with that name to a Widget + * that should be displayed below the dropdown. Changing the dropdown selection will then change + * the widget displayed. + */ +public interface AppNavigationView extends IsWidget, + IsMaskable, + HasSelectionHandlers { + + /** + * Add a category/hierarchy root to the view with the specified name + * @param widget + * @param name + */ + void add(Widget widget, String name); + + /** + * Add a category/hierarchy root to the view at the specified index with the specified name + * @param widget + * @param name + */ + void insert(Widget widget, int index, String name); + + /** + * Remove all options from the view + */ + void clear(); + + /** + * Set the navigation view to the specified widget + * @param widget + */ + void setActiveWidget(Widget widget); + + /** + * Return the widget at that particular index + * @param index + */ + Widget getWidget(int index); + + /** + * @return true if there are no options in the view + */ + boolean isEmpty(); + + /** + * @return the list of all widgets added to the view + */ + List getWidgets(); + + /** + * @return the count of all the options in the view + */ + int getWidgetCount(); +} diff --git a/de-lib/src/main/java/org/iplantc/de/apps/client/AppsView.java b/de-lib/src/main/java/org/iplantc/de/apps/client/AppsView.java index e0b4133e7f..48a58ec8d6 100644 --- a/de-lib/src/main/java/org/iplantc/de/apps/client/AppsView.java +++ b/de-lib/src/main/java/org/iplantc/de/apps/client/AppsView.java @@ -1,10 +1,10 @@ package org.iplantc.de.apps.client; +import org.iplantc.de.apps.client.AppNavigationView; import org.iplantc.de.client.models.HasId; import org.iplantc.de.client.models.IsMaskable; import org.iplantc.de.client.models.apps.App; import org.iplantc.de.client.models.apps.AppCategory; -import org.iplantc.de.commons.client.widgets.DETabPanel; import com.google.gwt.user.client.ui.HasOneWidget; import com.google.gwt.user.client.ui.IsWidget; @@ -84,13 +84,13 @@ void go(HasOneWidget container, public boolean isDetailsCollapsed(); } - DETabPanel getCategoryTabPanel(); + AppNavigationView getAppNavigationView(); void hideAppMenu(); void hideWorkflowMenu(); - void clearTabPanel(); + void resetAppNavigationView(); boolean isNavPanelCollapsed(); diff --git a/de-lib/src/main/java/org/iplantc/de/apps/client/OntologyHierarchiesView.java b/de-lib/src/main/java/org/iplantc/de/apps/client/OntologyHierarchiesView.java index 9d6b52dbe2..a095be2a05 100644 --- a/de-lib/src/main/java/org/iplantc/de/apps/client/OntologyHierarchiesView.java +++ b/de-lib/src/main/java/org/iplantc/de/apps/client/OntologyHierarchiesView.java @@ -4,9 +4,9 @@ import org.iplantc.de.apps.client.events.SelectedHierarchyNotFound; import org.iplantc.de.apps.client.events.selection.AppInfoSelectedEvent; import org.iplantc.de.apps.client.events.selection.OntologyHierarchySelectionChangedEvent; +import org.iplantc.de.apps.client.AppNavigationView; import org.iplantc.de.client.models.IsMaskable; import org.iplantc.de.client.models.ontologies.OntologyHierarchy; -import org.iplantc.de.commons.client.widgets.DETabPanel; import com.google.gwt.user.client.ui.IsWidget; @@ -31,7 +31,7 @@ interface Presenter extends AppInfoSelectedEvent.AppInfoSelectedEventHandler, OntologyHierarchySelectionChangedEvent.HasOntologyHierarchySelectionChangedEventHandlers, SelectedHierarchyNotFound.HasSelectedHierarchyNotFoundHandlers { - void go(OntologyHierarchy selectedHierarchy, DETabPanel tabPanel); + void go(OntologyHierarchy selectedHierarchy, AppNavigationView appNavigationView); void setViewDebugId(String baseID); diff --git a/de-lib/src/main/java/org/iplantc/de/apps/client/gin/AppsGinModule.java b/de-lib/src/main/java/org/iplantc/de/apps/client/gin/AppsGinModule.java index 4d7ade9ba3..7ef4612471 100644 --- a/de-lib/src/main/java/org/iplantc/de/apps/client/gin/AppsGinModule.java +++ b/de-lib/src/main/java/org/iplantc/de/apps/client/gin/AppsGinModule.java @@ -2,6 +2,7 @@ import org.iplantc.de.apps.client.AppCategoriesView; import org.iplantc.de.apps.client.AppDetailsView; +import org.iplantc.de.apps.client.AppNavigationView; import org.iplantc.de.apps.client.AppsListView; import org.iplantc.de.apps.client.AppsToolbarView; import org.iplantc.de.apps.client.AppsView; @@ -33,6 +34,7 @@ import org.iplantc.de.apps.client.views.list.AppsGridViewImpl; import org.iplantc.de.apps.client.views.list.AppsTileViewImpl; import org.iplantc.de.apps.client.views.list.widgets.AppTypeFilterCombo; +import org.iplantc.de.apps.client.views.navigation.AppNavigationViewImpl; import org.iplantc.de.apps.client.views.sharing.AppSharingView; import org.iplantc.de.apps.client.views.sharing.AppSharingViewImpl; import org.iplantc.de.apps.client.views.submit.SubmitAppForPublicUseViewImpl; @@ -116,6 +118,9 @@ protected void configure() { install(new GinFactoryModuleBuilder().implement(AppDocEditView.class, AppDocEditViewImpl.class) .build(AppDocEditViewFactory.class)); + // Navigation + bind(AppNavigationView.class).to(AppNavigationViewImpl.class); + bind(AppDetailsView.Presenter.class).to(AppDetailsViewPresenterImpl.class); bind(AppDetailsDialog.class); diff --git a/de-lib/src/main/java/org/iplantc/de/apps/client/presenter/AppsViewPresenterImpl.java b/de-lib/src/main/java/org/iplantc/de/apps/client/presenter/AppsViewPresenterImpl.java index 752bf83653..f24ed8873d 100644 --- a/de-lib/src/main/java/org/iplantc/de/apps/client/presenter/AppsViewPresenterImpl.java +++ b/de-lib/src/main/java/org/iplantc/de/apps/client/presenter/AppsViewPresenterImpl.java @@ -7,13 +7,13 @@ import org.iplantc.de.apps.client.OntologyHierarchiesView; import org.iplantc.de.apps.client.events.selection.RefreshAppsSelectedEvent; import org.iplantc.de.apps.client.gin.factory.AppsViewFactory; +import org.iplantc.de.apps.client.AppNavigationView; import org.iplantc.de.client.models.HasId; import org.iplantc.de.client.models.UserInfo; import org.iplantc.de.client.models.apps.App; import org.iplantc.de.client.models.apps.AppCategory; import org.iplantc.de.client.models.ontologies.OntologyHierarchy; import org.iplantc.de.client.util.OntologyUtil; -import org.iplantc.de.commons.client.widgets.DETabPanel; import com.google.common.base.Strings; import com.google.gwt.user.client.ui.HasOneWidget; @@ -97,10 +97,10 @@ public AppCategory getSelectedAppCategory() { public void go(final HasOneWidget container, final HasId selectedAppCategory, final HasId selectedApp, final String activeView, final boolean catPanelCollapsed) { - DETabPanel tabPanel = view.getCategoryTabPanel(); - if (isEmpty(tabPanel)) { - categoriesPresenter.go(selectedAppCategory, true, tabPanel); - hierarchiesPresenter.go(null, tabPanel); + AppNavigationView appNavigationView = view.getAppNavigationView(); + if (appNavigationView.isEmpty()) { + categoriesPresenter.go(selectedAppCategory, true, appNavigationView); + hierarchiesPresenter.go(null, appNavigationView); } if (!Strings.isNullOrEmpty(activeView)) { appsListPresenter.setActiveView(activeView); @@ -163,11 +163,11 @@ public void onRefreshAppsSelected(RefreshAppsSelectedEvent event) { boolean hasSearchPhrase = toolbarPresenter.getView().hasSearchPhrase(); boolean useDefaultSelection = !hasSearchPhrase && selectedHierarchy == null; - view.clearTabPanel(); - DETabPanel categoryTabPanel = view.getCategoryTabPanel(); + view.resetAppNavigationView(); + AppNavigationView appNavigationView = view.getAppNavigationView(); - categoriesPresenter.go(selectedAppCategory, useDefaultSelection, categoryTabPanel); - hierarchiesPresenter.go(selectedHierarchy, categoryTabPanel); + categoriesPresenter.go(selectedAppCategory, useDefaultSelection, appNavigationView); + hierarchiesPresenter.go(selectedHierarchy, appNavigationView); if (hasSearchPhrase) { toolbarPresenter.reloadSearchResults(); } diff --git a/de-lib/src/main/java/org/iplantc/de/apps/client/presenter/categories/AppCategoriesPresenterImpl.java b/de-lib/src/main/java/org/iplantc/de/apps/client/presenter/categories/AppCategoriesPresenterImpl.java index cdbbdb4932..2a3c9bb23e 100644 --- a/de-lib/src/main/java/org/iplantc/de/apps/client/presenter/categories/AppCategoriesPresenterImpl.java +++ b/de-lib/src/main/java/org/iplantc/de/apps/client/presenter/categories/AppCategoriesPresenterImpl.java @@ -12,6 +12,7 @@ import org.iplantc.de.apps.client.events.selection.CopyWorkflowSelected; import org.iplantc.de.apps.client.gin.AppCategoryTreeStoreProvider; import org.iplantc.de.apps.client.gin.factory.AppCategoriesViewFactory; +import org.iplantc.de.apps.client.AppNavigationView; import org.iplantc.de.apps.client.views.details.dialogs.AppDetailsDialog; import org.iplantc.de.apps.shared.AppsModule; import org.iplantc.de.client.events.EventBus; @@ -29,7 +30,6 @@ import org.iplantc.de.commons.client.info.IplantAnnouncer; import org.iplantc.de.commons.client.info.SuccessAnnouncementConfig; import org.iplantc.de.commons.client.views.dialogs.AgaveAuthPrompt; -import org.iplantc.de.commons.client.widgets.DETabPanel; import org.iplantc.de.shared.AppsCallback; import org.iplantc.de.shared.AsyncProviderWrapper; import org.iplantc.de.shared.DEProperties; @@ -54,7 +54,6 @@ import com.sencha.gxt.data.shared.SortDir; import com.sencha.gxt.data.shared.Store; import com.sencha.gxt.data.shared.TreeStore; -import com.sencha.gxt.widget.core.client.TabItemConfig; import com.sencha.gxt.widget.core.client.tree.Tree; import java.util.Arrays; @@ -108,7 +107,7 @@ public int compare(AppCategory group1, AppCategory group2) { List workspaceCategories = Lists.newArrayList(); List hpcCategories = Lists.newArrayList(); List> trees = Lists.newArrayList(); - DETabPanel viewTabPanel; + AppNavigationView appNavigationView; AppCategoriesViewFactory viewFactory; HandlerManager handlerManager; AppCategoriesView workspaceView; @@ -167,11 +166,11 @@ public AppCategoriesView getWorkspaceView() { } @Override - public void go(final HasId selectedAppCategory, final boolean selectDefaultCategory, final DETabPanel tabPanel) { - this.viewTabPanel = tabPanel; + public void go(final HasId selectedAppCategory, final boolean selectDefaultCategory, final AppNavigationView appNavigationView) { + this.appNavigationView = appNavigationView; - viewTabPanel.add(workspaceView.getTree(), new TabItemConfig(appearance.workspaceTab()), baseId + AppsModule.Ids.WORKSPACE_TAB); - viewTabPanel.add(hpcView.getTree(), new TabItemConfig(appearance.hpcTab()), baseId + AppsModule.Ids.HPC_TAB); + this.appNavigationView.add(workspaceView.getTree(), appearance.workspaceTab()); + this.appNavigationView.add(hpcView.getTree(), appearance.hpcTab()); workspaceView.getTree().mask(appearance.getAppCategoriesLoadingMask()); hpcView.getTree().mask(appearance.getAppCategoriesLoadingMask()); @@ -180,7 +179,7 @@ public void go(final HasId selectedAppCategory, final boolean selectDefaultCateg @Override public void onFailure(Integer statusCode, Throwable caught) { ErrorHandler.post(caught); - viewTabPanel.unmask(); + appNavigationView.unmask(); } @Override @@ -247,7 +246,7 @@ void selectDesiredCategory(HasId selectedAppCategory, boolean selectDefaultCateg boolean doSelectCategory(Tree tree, AppCategory category) { Tree.TreeNode node = tree.findNode(category); if (node != null) { - viewTabPanel.setActiveWidget(tree); + appNavigationView.setActiveWidget(tree); tree.getSelectionModel().select(node.getModel(), true); return true; } @@ -256,7 +255,7 @@ boolean doSelectCategory(Tree tree, AppCategory category) { void selectDefaultCategory() { Tree tree = workspaceView.getTree(); - viewTabPanel.setActiveWidget(tree); + appNavigationView.setActiveWidget(tree); tree.getSelectionModel().select(tree.getStore().getRootItems().get(0), true); } @@ -266,7 +265,7 @@ public void onSelectedHierarchyNotFound(SelectedHierarchyNotFound event) { } void addHPCTabSelectionHandler() { - viewTabPanel.addSelectionHandler(new SelectionHandler() { + appNavigationView.addSelectionHandler(new SelectionHandler() { @Override public void onSelection(SelectionEvent event) { if (event.getSelectedItem() == hpcView.getTree() && hpcCategories.size() == 1) { diff --git a/de-lib/src/main/java/org/iplantc/de/apps/client/presenter/hierarchies/OntologyHierarchiesPresenterImpl.java b/de-lib/src/main/java/org/iplantc/de/apps/client/presenter/hierarchies/OntologyHierarchiesPresenterImpl.java index d53d5c17c1..9787effb32 100644 --- a/de-lib/src/main/java/org/iplantc/de/apps/client/presenter/hierarchies/OntologyHierarchiesPresenterImpl.java +++ b/de-lib/src/main/java/org/iplantc/de/apps/client/presenter/hierarchies/OntologyHierarchiesPresenterImpl.java @@ -20,6 +20,7 @@ import org.iplantc.de.apps.client.presenter.callbacks.DeleteRatingCallback; import org.iplantc.de.apps.client.presenter.callbacks.ParentFilteredHierarchyCallback; import org.iplantc.de.apps.client.presenter.callbacks.RateAppCallback; +import org.iplantc.de.apps.client.AppNavigationView; import org.iplantc.de.apps.client.views.details.dialogs.AppDetailsDialog; import org.iplantc.de.client.events.EventBus; import org.iplantc.de.client.models.apps.App; @@ -31,7 +32,6 @@ import org.iplantc.de.commons.client.ErrorHandler; import org.iplantc.de.commons.client.info.ErrorAnnouncementConfig; import org.iplantc.de.commons.client.info.IplantAnnouncer; -import org.iplantc.de.commons.client.widgets.DETabPanel; import org.iplantc.de.shared.AppsCallback; import com.google.common.collect.Lists; @@ -47,7 +47,6 @@ import com.sencha.gxt.data.shared.SortDir; import com.sencha.gxt.data.shared.Store; import com.sencha.gxt.data.shared.TreeStore; -import com.sencha.gxt.widget.core.client.TabItemConfig; import com.sencha.gxt.widget.core.client.tree.Tree; import java.util.List; @@ -155,7 +154,7 @@ public void setParent(ParentFilteredHierarchyCallback parent) { OntologyUtil ontologyUtil; @Inject AsyncProvider appDetailsDlgAsyncProvider; @Inject AppUserServiceFacade appUserService; - DETabPanel viewTabPanel; + AppNavigationView appNavigationView; private OntologyServiceFacade serviceFacade; private OntologyHierarchiesView.OntologyHierarchiesAppearance appearance; protected String searchRegexPattern; @@ -184,11 +183,11 @@ public OntologyHierarchiesPresenterImpl(OntologyHierarchiesViewFactory viewFacto } @Override - public void go(final OntologyHierarchy selectedHierarchy, final DETabPanel tabPanel) { + public void go(final OntologyHierarchy selectedHierarchy, final AppNavigationView appNavigationView) { desiredHierarchyFound = false; unclassifiedHierarchies = Lists.newArrayList(); views = Lists.newArrayList(); - viewTabPanel = tabPanel; + this.appNavigationView = appNavigationView; serviceFacade.getRootHierarchies(new AppsCallback>() { @Override public void onFailure(Integer statusCode, Throwable caught) { @@ -258,7 +257,7 @@ void createViewTabs(final OntologyHierarchy selectedHierarchy, List tree, OntologyHierarchy selectedHierarchy) { Tree.TreeNode node = tree.findNode(selectedHierarchy); if (node != null) { - viewTabPanel.setActiveWidget(tree); + appNavigationView.setActiveWidget(tree); tree.getSelectionModel().select(node.getModel(), true); return true; } @@ -408,11 +407,11 @@ public void onDetailsHierarchyClicked(DetailsHierarchyClicked event) { checkNotNull(hierarchy); String id = ontologyUtil.getOrCreateHierarchyPathTag(hierarchy); - for (int i = 0; i < viewTabPanel.getWidgetCount(); i++) { - Tree tree = ((Tree)viewTabPanel.getWidget(i)); + for (int i = 0; i < appNavigationView.getWidgetCount(); i++) { + Tree tree = ((Tree)appNavigationView.getWidget(i)); OntologyHierarchy selectedHierarchy = tree.getStore().findModelWithKey(id); if (selectedHierarchy != null) { - viewTabPanel.setActiveWidget(tree); + appNavigationView.setActiveWidget(tree); tree.scrollIntoView(selectedHierarchy); tree.getSelectionModel().select(selectedHierarchy, true); break; @@ -425,11 +424,11 @@ public void onDetailsCategoryClicked(DetailsCategoryClicked event) { AppCategory category = event.getCategory(); checkNotNull(category); - for (int i = 0 ; i < viewTabPanel.getWidgetCount() ; i++) { - Tree tree = ((Tree)viewTabPanel.getWidget(i)); + for (int i = 0; i < appNavigationView.getWidgetCount() ; i++) { + Tree tree = ((Tree)appNavigationView.getWidget(i)); AppCategory selectedCategory = tree.getStore().findModelWithKey(category.getId()); if (selectedCategory != null) { - viewTabPanel.setActiveWidget(tree); + appNavigationView.setActiveWidget(tree); tree.scrollIntoView(selectedCategory); tree.getSelectionModel().select(selectedCategory, true); break; diff --git a/de-lib/src/main/java/org/iplantc/de/apps/client/views/AppsView.ui.xml b/de-lib/src/main/java/org/iplantc/de/apps/client/views/AppsView.ui.xml index 200477c098..e347063051 100644 --- a/de-lib/src/main/java/org/iplantc/de/apps/client/views/AppsView.ui.xml +++ b/de-lib/src/main/java/org/iplantc/de/apps/client/views/AppsView.ui.xml @@ -2,9 +2,8 @@ + xmlns:de="urn:import:org.iplantc.de.apps.client"> - - - + diff --git a/de-lib/src/main/java/org/iplantc/de/apps/client/views/AppsViewImpl.java b/de-lib/src/main/java/org/iplantc/de/apps/client/views/AppsViewImpl.java index aabf59b72d..3aad98e916 100644 --- a/de-lib/src/main/java/org/iplantc/de/apps/client/views/AppsViewImpl.java +++ b/de-lib/src/main/java/org/iplantc/de/apps/client/views/AppsViewImpl.java @@ -1,19 +1,19 @@ package org.iplantc.de.apps.client.views; import org.iplantc.de.apps.client.AppCategoriesView; +import org.iplantc.de.apps.client.AppNavigationView; import org.iplantc.de.apps.client.AppsListView; import org.iplantc.de.apps.client.AppsToolbarView; import org.iplantc.de.apps.client.AppsView; import org.iplantc.de.apps.client.OntologyHierarchiesView; import org.iplantc.de.apps.shared.AppsModule.Ids; import org.iplantc.de.client.models.apps.AppCategory; -import org.iplantc.de.commons.client.widgets.DETabPanel; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.Scheduler; -import com.google.gwt.event.logical.shared.SelectionEvent; import com.google.gwt.event.logical.shared.SelectionHandler; import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiFactory; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiTemplate; import com.google.gwt.user.client.ui.Widget; @@ -37,7 +37,7 @@ interface MyUiBinder extends UiBinder { } @UiField(provided = true) final AppsToolbarView toolBar; - @UiField DETabPanel categoryTabs; + @UiField(provided = true) AppNavigationView appNavigationView; @UiField ContentPanel westPanel; AppCategoriesView.Presenter categoriesPresenter; @@ -55,28 +55,27 @@ interface MyUiBinder extends UiBinder { protected AppsViewImpl(@Assisted final AppCategoriesView.Presenter categoriesPresenter, @Assisted final OntologyHierarchiesView.Presenter hierarchiesPresenter, @Assisted final AppsListView.Presenter gridPresenter, - @Assisted final AppsToolbarView.Presenter toolbarPresenter) { + @Assisted final AppsToolbarView.Presenter toolbarPresenter, + AppNavigationView appNavigationView) { this.categoriesPresenter = categoriesPresenter; this.hierarchiesPresenter = hierarchiesPresenter; this.gridPresenter = gridPresenter; this.toolBar = toolbarPresenter.getView(); + this.appNavigationView = appNavigationView; initWidget(uiBinder.createAndBindUi(this)); - categoryTabs.addSelectionHandler(new SelectionHandler() { - @Override - public void onSelection(SelectionEvent event) { - Widget selectedItem = event.getSelectedItem(); - for (Widget currentItem : categoryTabs) { - if (currentItem != selectedItem) { - ((Tree)currentItem).getSelectionModel().deselectAll(); - } - } - List items = ((Tree)selectedItem).getStore().getRootItems(); - if (items != null && items.size() > 0) { - ((Tree)selectedItem).getSelectionModel().select(items.get(0), false); + appNavigationView.addSelectionHandler(event -> { + Widget selectedItem = event.getSelectedItem(); + for (Widget currentItem : appNavigationView.getWidgets()) { + if (currentItem != selectedItem) { + ((Tree)currentItem).getSelectionModel().deselectAll(); } } + List items = ((Tree)selectedItem).getStore().getRootItems(); + if (items != null && items.size() > 0) { + ((Tree)selectedItem).getSelectionModel().select(items.get(0), false); + } }); gridPresenter.go(cardContainer); @@ -93,8 +92,8 @@ public void setWestPanelWidth(String width) { } @Override - public DETabPanel getCategoryTabPanel() { - return categoryTabs; + public AppNavigationView getAppNavigationView() { + return appNavigationView; } @Override @@ -107,13 +106,8 @@ public void hideWorkflowMenu() { toolBar.hideWorkflowMenu(); } - public void clearTabPanel() { - categoryTabs.disableEvents(); - int tabCount = categoryTabs.getWidgetCount(); - for (int i = 0 ; i < tabCount ; i++) { - categoryTabs.close(categoryTabs.getWidget(0)); - } - categoryTabs.enableEvents(); + public void resetAppNavigationView() { + appNavigationView.clear(); } @Override diff --git a/de-lib/src/main/java/org/iplantc/de/apps/client/views/navigation/AppNavigationViewImpl.java b/de-lib/src/main/java/org/iplantc/de/apps/client/views/navigation/AppNavigationViewImpl.java new file mode 100644 index 0000000000..e3dd8ed0e9 --- /dev/null +++ b/de-lib/src/main/java/org/iplantc/de/apps/client/views/navigation/AppNavigationViewImpl.java @@ -0,0 +1,120 @@ +package org.iplantc.de.apps.client.views.navigation; + +import org.iplantc.de.apps.client.AppNavigationView; + +import com.google.common.collect.Lists; +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.logical.shared.SelectionEvent; +import com.google.gwt.event.logical.shared.SelectionHandler; +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiFactory; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Widget; +import com.google.inject.Inject; + +import com.sencha.gxt.data.shared.StringLabelProvider; +import com.sencha.gxt.widget.core.client.Composite; +import com.sencha.gxt.widget.core.client.container.CardLayoutContainer; +import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer; +import com.sencha.gxt.widget.core.client.form.SimpleComboBox; + +import java.util.HashMap; +import java.util.List; + +/** + * @author aramsey + */ +public class AppNavigationViewImpl extends Composite implements AppNavigationView { + + interface AppNavigationViewImplUiBinder extends UiBinder {} + private static final AppNavigationViewImplUiBinder uiBinder = GWT.create(AppNavigationViewImplUiBinder.class); + + @UiField VerticalLayoutContainer vlc; + @UiField SimpleComboBox combo; + @UiField CardLayoutContainer container; + private HashMap selectionMap; + + @Inject + public AppNavigationViewImpl() { + initWidget(uiBinder.createAndBindUi(this)); + selectionMap = new HashMap<>(); + } + + @UiFactory + SimpleComboBox createComboBox() { + SimpleComboBox combo = new SimpleComboBox<>(new StringLabelProvider<>()); + combo.addSelectionHandler(event -> { + String selectedName = event.getSelectedItem(); + int index = combo.getStore().indexOf(selectedName); + container.setActiveWidget(container.getWidget(index)); + SelectionEvent.fire(this, container.getActiveWidget()); + }); + return combo; + } + + @Override + public void mask() { + vlc.mask(); + } + + @Override + public void unmask() { + vlc.unmask(); + } + + @Override + public void add(Widget widget, String name) { + insert(widget, container.getWidgetCount(), name); + } + + @Override + public void insert(Widget widget, int index, String name) { + if (!selectionMap.containsKey(widget)) { + combo.getStore().add(index, name); + selectionMap.put(widget, name); + container.insert(widget, index); + // Make sure if this is the only Widget, that Widget is shown + if (container.getWidgetCount() == 1) { + container.setActiveWidget(container.getWidget(0)); + } + } + } + + @Override + public void clear() { + selectionMap.clear(); + combo.getStore().clear(); + container.clear(); + } + + @Override + public void setActiveWidget(Widget widget) { + container.setActiveWidget(widget); + combo.setText(selectionMap.get(widget)); + } + + + public Widget getWidget(int index) { + return container.getWidget(index); + } + + public List getWidgets() { + return Lists.newArrayList(selectionMap.keySet()); + } + + @Override + public boolean isEmpty() { + return container.getWidgetCount() == 0; + } + + @Override + public int getWidgetCount() { + return container.getWidgetCount(); + } + + @Override + public HandlerRegistration addSelectionHandler(SelectionHandler handler) { + return addHandler(handler, SelectionEvent.getType()); + } +} diff --git a/de-lib/src/main/java/org/iplantc/de/apps/client/views/navigation/AppNavigationViewImpl.ui.xml b/de-lib/src/main/java/org/iplantc/de/apps/client/views/navigation/AppNavigationViewImpl.ui.xml new file mode 100644 index 0000000000..9537ddf8b3 --- /dev/null +++ b/de-lib/src/main/java/org/iplantc/de/apps/client/views/navigation/AppNavigationViewImpl.ui.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + diff --git a/de-lib/src/test/java/org/iplantc/de/apps/client/presenter/categories/AppCategoriesPresenterImplTest.java b/de-lib/src/test/java/org/iplantc/de/apps/client/presenter/categories/AppCategoriesPresenterImplTest.java index e9437086db..4866822943 100644 --- a/de-lib/src/test/java/org/iplantc/de/apps/client/presenter/categories/AppCategoriesPresenterImplTest.java +++ b/de-lib/src/test/java/org/iplantc/de/apps/client/presenter/categories/AppCategoriesPresenterImplTest.java @@ -14,6 +14,7 @@ import static org.mockito.Mockito.when; import org.iplantc.de.apps.client.AppCategoriesView; +import org.iplantc.de.apps.client.AppNavigationView; import org.iplantc.de.apps.client.events.AppSavedEvent; import org.iplantc.de.apps.client.events.AppSearchResultLoadEvent; import org.iplantc.de.apps.client.events.selection.CopyAppSelected; @@ -27,7 +28,6 @@ import org.iplantc.de.client.services.AppServiceFacade; import org.iplantc.de.client.services.AppUserServiceFacade; import org.iplantc.de.client.util.JsonUtil; -import org.iplantc.de.commons.client.widgets.DETabPanel; import org.iplantc.de.shared.AsyncProviderWrapper; import org.iplantc.de.shared.DECallback; import org.iplantc.de.shared.DEProperties; @@ -75,7 +75,7 @@ public class AppCategoriesPresenterImplTest { @Mock AppCategoriesView.AppCategoriesAppearance appearanceMock; @Mock Tree treeMock; @Mock TreeSelectionModel selectionModelMock; - @Mock DETabPanel tabPanelMock; + @Mock AppNavigationView appNavigationViewMock; @Mock List> treesMock; @Mock Iterator> treesIteratorMock; @Mock AppCategory categoryMock; @@ -129,7 +129,7 @@ public class AppCategoriesPresenterImplTest { uut.workspaceView = workspaceViewMock; uut.hpcView = hpcViewMock; uut.trees = treesMock; - uut.viewTabPanel = tabPanelMock; + uut.appNavigationView = appNavigationViewMock; } @Test public void testConstructorEventHandlerWiring() { @@ -152,7 +152,7 @@ public class AppCategoriesPresenterImplTest { when(appearanceMock.hpcTab()).thenReturn("hpc"); /*** CALL METHOD UNDER TEST ***/ - uut.go(null, false, tabPanelMock); + uut.go(null, false, appNavigationViewMock); verify(treeMock, times(2)).mask(anyString()); verify(appServiceMock).getAppCategories(anyBoolean(), appCategoriesCaptor.capture()); @@ -267,7 +267,7 @@ public void testSelectDefaultCategory() { /*** CALL METHOD UNDER TEST ***/ uut.selectDefaultCategory(); - verify(tabPanelMock).setActiveWidget(treeMock); + verify(appNavigationViewMock).setActiveWidget(treeMock); verify(selectionModelMock).select(isA(AppCategory.class), eq(true)); } diff --git a/de-lib/src/test/java/org/iplantc/de/apps/client/presenter/hierarchies/OntologyHierarchiesPresenterImplTest.java b/de-lib/src/test/java/org/iplantc/de/apps/client/presenter/hierarchies/OntologyHierarchiesPresenterImplTest.java index 2df4170b23..b4ce7813a7 100644 --- a/de-lib/src/test/java/org/iplantc/de/apps/client/presenter/hierarchies/OntologyHierarchiesPresenterImplTest.java +++ b/de-lib/src/test/java/org/iplantc/de/apps/client/presenter/hierarchies/OntologyHierarchiesPresenterImplTest.java @@ -17,6 +17,7 @@ import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; +import org.iplantc.de.apps.client.AppNavigationView; import org.iplantc.de.apps.client.OntologyHierarchiesView; import org.iplantc.de.apps.client.events.AppFavoritedEvent; import org.iplantc.de.apps.client.events.AppSearchResultLoadEvent; @@ -42,7 +43,6 @@ import org.iplantc.de.client.util.OntologyUtil; import org.iplantc.de.commons.client.info.ErrorAnnouncementConfig; import org.iplantc.de.commons.client.info.IplantAnnouncer; -import org.iplantc.de.commons.client.widgets.DETabPanel; import org.iplantc.de.shared.DECallback; import com.google.gwt.event.shared.HandlerManager; @@ -78,7 +78,7 @@ public class OntologyHierarchiesPresenterImplTest { @Mock OntologyUtil ontologyUtilMock; @Mock AsyncProvider appDetailsDialogProviderMock; @Mock AppUserServiceFacade appUserServiceMock; - @Mock DETabPanel tabPanelMock; + @Mock AppNavigationView appNavigationViewMock; @Mock OntologyServiceFacade ontologyServiceMock; @Mock OntologyHierarchiesView.OntologyHierarchiesAppearance appearanceMock; @Mock EventBus eventBusMock; @@ -100,6 +100,7 @@ public class OntologyHierarchiesPresenterImplTest { @Mock OntologyHierarchiesView viewMock; @Mock Tree hierarchyTreeMock; @Mock Tree categoryTreeMock; + @Mock List widgetsMock; @Mock Iterator tabPanelIteratorMock; @Mock Widget randomWidgetMock; @Mock TreeSelectionModel treeSelectionModelMock; @@ -149,9 +150,10 @@ public void setUp() { when(hierarchyTreeMock.getSelectionModel()).thenReturn(treeSelectionModelMock); when(hierarchyTreeMock.getStore()).thenReturn(hierarchyTreeStoreMock); when(hierarchyTreeStoreMock.findModelWithKey(anyString())).thenReturn(hierarchyMock); - when(tabPanelMock.getWidgetCount()).thenReturn(2); - when(tabPanelMock.iterator()).thenReturn(tabPanelIteratorMock); - when(tabPanelMock.getWidget(anyInt())).thenReturn(hierarchyTreeMock); + when(appNavigationViewMock.getWidgetCount()).thenReturn(2); + when(appNavigationViewMock.getWidgets()).thenReturn(widgetsMock); + when(widgetsMock.iterator()).thenReturn(tabPanelIteratorMock); + when(appNavigationViewMock.getWidget(anyInt())).thenReturn(hierarchyTreeMock); when(tabPanelIteratorMock.hasNext()).thenReturn(true, true, false); when(tabPanelIteratorMock.next()).thenReturn(hierarchyTreeMock).thenReturn(randomWidgetMock); when(appMock.getHierarchies()).thenReturn(hierarchyListMock); @@ -195,7 +197,7 @@ List createFilteredHierarchyList() { uut.handlerManager = handlerManagerMock; uut.iriToHierarchyMap = iriToHierarchyMapMock; uut.searchRegexPattern = "test"; - uut.viewTabPanel = tabPanelMock; + uut.appNavigationView = appNavigationViewMock; uut.unclassifiedHierarchies = unclassifiedHierarchiesMock; uut.views = viewsMock; } @@ -223,7 +225,7 @@ void createViewTabs(OntologyHierarchy selectedHierarchy, List uut.iriToHierarchyMap = iriToHierarchyMapMock; /** CALL METHOD UNDER TEST **/ - uut.go(hierarchyMock, tabPanelMock); + uut.go(hierarchyMock, appNavigationViewMock); verify(ontologyServiceMock).getRootHierarchies(hierarchyListCallback.capture()); hierarchyListCallback.getValue().onSuccess(hierarchyListMock); @@ -251,7 +253,7 @@ void createViewTabs(OntologyHierarchy selectedHierarchy, List uut.iriToHierarchyMap = iriToHierarchyMapMock; /** CALL METHOD UNDER TEST **/ - uut.go(hierarchyMock, tabPanelMock); + uut.go(hierarchyMock, appNavigationViewMock); verify(ontologyServiceMock).getRootHierarchies(hierarchyListCallback.capture()); hierarchyListCallback.getValue().onSuccess(hierarchyListMock); @@ -373,10 +375,9 @@ public void testCreateViewTabs() throws Exception { verify(viewMock).setRoot(hierarchyMock); verify(viewsMock).add(viewMock); verify(viewMock).addOntologyHierarchySelectionChangedEventHandler(spy); - verify(tabPanelMock).insert(eq(hierarchyTreeMock), - anyInt(), - isA(TabItemConfig.class), - anyString()); + verify(appNavigationViewMock).insert(eq(hierarchyTreeMock), + anyInt(), + anyString()); verify(spy).populateViewTabs(selectedHierarchy); } @@ -484,9 +485,9 @@ public void testOnDetailsHierarchyClicked() { /*** CALL METHOD UNDER TEST ***/ uut.onDetailsHierarchyClicked(eventMock); - verify(tabPanelMock).getWidget(anyInt()); + verify(appNavigationViewMock).getWidget(anyInt()); verify(hierarchyTreeStoreMock).findModelWithKey(anyString()); - verify(tabPanelMock).setActiveWidget(eq(hierarchyTreeMock)); + verify(appNavigationViewMock).setActiveWidget(eq(hierarchyTreeMock)); verify(treeSelectionModelMock).select(eq(hierarchyMock), anyBoolean()); } @@ -494,14 +495,14 @@ public void testOnDetailsHierarchyClicked() { public void testOnDetailsCategoryClicked() { DetailsCategoryClicked eventMock = mock(DetailsCategoryClicked.class); when(eventMock.getCategory()).thenReturn(appCategoryMock); - when(tabPanelMock.getWidget(anyInt())).thenReturn(categoryTreeMock); + when(appNavigationViewMock.getWidget(anyInt())).thenReturn(categoryTreeMock); /*** CALL METHOD UNDER TEST ***/ uut.onDetailsCategoryClicked(eventMock); - verify(tabPanelMock).getWidget(anyInt()); + verify(appNavigationViewMock).getWidget(anyInt()); verify(categoryTreeStoreMock).findModelWithKey(anyString()); - verify(tabPanelMock).setActiveWidget(eq(categoryTreeMock)); + verify(appNavigationViewMock).setActiveWidget(eq(categoryTreeMock)); verify(categoryTreeSelectionModelMock).select(eq(appCategoryMock), anyBoolean()); }