From 19c02f2782172faca69af706164cb4265a4fe525 Mon Sep 17 00:00:00 2001 From: Aleksandr Pchelintcev Date: Fri, 7 Feb 2014 09:52:15 +0200 Subject: [PATCH] Preparing patch --- magnolia-ui-actionbar/pom.xml | 5 + .../magnolia/ui/actionbar/ActionbarPresenter.java | 132 +++--- .../info/magnolia/ui/actionbar/ActionbarView.java | 87 ++++ .../magnolia/ui/actionbar/ActionbarViewImpl.java | 153 +++++++ .../ui/actionbar/builder/ActionbarFactory.java | 114 ----- .../ui/actionbar/ActionbarPresenterTest.java | 274 +++++++++++ .../ui/actionbar/builder/ActionbarFactoryTest.java | 295 ------------ .../dialog/action/SaveDialogAction.java | 2 +- .../shellapp/favorites/FavoritesManagerImpl.java | 2 +- .../shellapp/pulse/message/MessagePresenter.java | 19 +- .../META-INF/magnolia/ui-admincentral.xml | 8 + magnolia-ui-api/pom.xml | 4 + .../java/info/magnolia/ui/api/ModelConstants.java | 45 -- .../ui/api/action/AbstractActionExecutor.java | 49 +- .../magnolia/ui/api/action/ActionExecutor.java | 3 +- .../api/availability/AbstractAvailabilityRule.java | 3 +- .../ui/api/availability/AvailabilityRule.java | 2 +- .../ui/api/availability/HasVersionsRule.java | 14 +- .../ui/api/availability/IsDeletedRule.java | 14 +- .../ui/api/availability/IsNotDeletedRule.java | 14 +- .../ui/api/availability/IsNotVersionedRule.java | 15 +- .../IsNotVersionedDetailLocationRule.java | 3 +- .../ui/contentapp/browser/BrowserPresenter.java | 328 ++------------ .../contentapp/browser/BrowserPresenterBase.java | 332 ++++++++++++++ .../ui/contentapp/browser/BrowserSubApp.java | 502 +++------------------ .../ui/contentapp/browser/BrowserSubAppBase.java | 501 ++++++++++++++++++++ .../ui/contentapp/browser/BrowserView.java | 2 +- .../ui/contentapp/browser/BrowserViewImpl.java | 2 +- .../browser/beanbrowser/BeanBrowserPresenter.java | 81 ++++ .../browser/beanbrowser/BeanBrowserSubApp.java | 75 +++ .../contentapp/detail/DetailEditorPresenter.java | 17 +- .../ui/contentapp/detail/DetailEditorView.java | 2 +- .../ui/contentapp/detail/DetailEditorViewImpl.java | 9 +- .../ui/contentapp/detail/DetailPresenter.java | 2 +- .../field/LinkFieldSelectionFactory.java | 3 +- .../ui/contentapp/field/WorkbenchField.java | 3 +- .../resources/META-INF/magnolia/ui-contentapp.xml | 5 + .../magnolia/ui/contentapp/ContentSubAppTest.java | 6 +- .../ui/contentapp/browser/BrowserSubAppTest.java | 231 +++------- .../dialog/formdialog/FormDialogPresenterImpl.java | 2 +- .../magnolia/ui/form/action/SaveFormAction.java | 2 +- .../resources/META-INF/magnolia/ui-framework.xml | 6 + .../framework/action/ConfirmationActionTest.java | 3 +- .../MediaEditorPresenterFactoryImpl.java | 18 +- .../ui/mediaeditor/MediaEditorPresenterImpl.java | 18 +- .../magnolia/ui/mediaeditor/MediaEditorView.java | 2 +- .../ui/mediaeditor/MediaEditorViewImpl.java | 19 +- .../ui/mediaeditor/action/ViewImageAction.java | 2 +- magnolia-ui-vaadin-common-widgets/pom.xml | 2 +- .../magnolia/ui/vaadin/actionbar/Actionbar.java | 81 ++-- .../ui/vaadin/actionbar/ActionbarView.java | 86 ---- magnolia-ui-vaadin-integration/pom.xml | 8 +- .../vaadin/integration/jcr/AbstractJcrAdapter.java | 2 - .../integration/jcr/AbstractJcrNodeAdapter.java | 1 - .../vaadin/integration/jcr/JcrNewNodeAdapter.java | 1 - .../vaadin/integration/jcr/JcrPropertyAdapter.java | 1 - .../ui/vaadin/integration/jcr/ModelConstants.java | 45 ++ .../jcr/AbstractJcrNodeAdapterTest.java | 1 - .../integration/jcr/JcrNewNodeAdapterTest.java | 1 - .../jcr/JcrNodeAdapterRepositoryTest.java | 1 - .../integration/jcr/JcrPropertyAdapterTest.java | 1 - .../ui/vaadin/gwt/MagnoliaWidgetSet.gwt.xml | 3 +- .../VAADIN/themes/admincentraltheme/shell.scss | 8 +- .../ui/workbench/AbstractContentPresenter.java | 204 +-------- .../ui/workbench/AbstractContentPresenterBase.java | 249 ++++++++++ .../magnolia/ui/workbench/ContentPresenter.java | 8 +- .../info/magnolia/ui/workbench/ContentView.java | 14 +- .../magnolia/ui/workbench/WorkbenchPresenter.java | 272 ++--------- .../ui/workbench/WorkbenchPresenterBase.java | 298 ++++++++++++ .../ui/workbench/WorkbenchStatusBarPresenter.java | 9 +- .../beanworkbench/BeanWorkbenchPresenter.java | 92 ++++ .../workbench/container/AbstractJcrContainer.java | 2 +- .../ui/workbench/event/ItemDoubleClickedEvent.java | 13 +- .../ui/workbench/event/ItemRightClickedEvent.java | 28 +- .../ui/workbench/event/ItemShortcutKeyEvent.java | 20 +- .../ui/workbench/event/SelectionChangedEvent.java | 52 +-- .../ui/workbench/list/FSListPresenter.java | 152 +++++++ .../magnolia/ui/workbench/list/ListPresenter.java | 15 +- .../magnolia/ui/workbench/list/ListViewImpl.java | 24 +- .../ui/workbench/search/SearchPresenter.java | 5 +- .../ui/workbench/thumbnail/ThumbnailContainer.java | 46 +- .../ui/workbench/thumbnail/ThumbnailPresenter.java | 46 +- .../ui/workbench/thumbnail/ThumbnailViewImpl.java | 19 +- .../magnolia/ui/workbench/tree/TreePresenter.java | 4 +- .../magnolia/ui/workbench/tree/TreeViewImpl.java | 84 ++-- .../container/AbstractJcrContainerTest.java | 2 +- .../ui/workbench/content/ContentPresenterTest.java | 2 +- .../workbench/search/SearchJcrContainerTest.java | 2 +- .../pages/app/action/CreateComponentAction.java | 2 +- .../PageHasSubpagesAndIsNotDeletedRule.java | 2 +- .../app/availability/PageHasSubpagesRule.java | 16 +- .../pages/app/editor/PagesEditorSubApp.java | 25 +- .../pages/app/editor/PagesEditorSubAppView.java | 2 +- .../app/editor/PagesEditorSubAppViewImpl.java | 2 +- .../action/availability/IsNotCurrentUserRule.java | 17 +- .../security/app/container/RoleTreePresenter.java | 4 +- .../security/app/container/UserTreePresenter.java | 4 +- .../app/dialog/action/SaveRoleDialogAction.java | 2 +- .../app/dialog/action/SaveUserDialogAction.java | 2 +- .../dialog/field/WorkspaceAccessFieldFactory.java | 2 +- .../dialog/action/SaveRoleDialogActionTest.java | 2 +- 101 files changed, 3069 insertions(+), 2347 deletions(-) create mode 100644 magnolia-ui-actionbar/src/main/java/info/magnolia/ui/actionbar/ActionbarView.java create mode 100644 magnolia-ui-actionbar/src/main/java/info/magnolia/ui/actionbar/ActionbarViewImpl.java delete mode 100644 magnolia-ui-actionbar/src/main/java/info/magnolia/ui/actionbar/builder/ActionbarFactory.java create mode 100644 magnolia-ui-actionbar/src/test/java/info/magnolia/ui/actionbar/ActionbarPresenterTest.java delete mode 100644 magnolia-ui-actionbar/src/test/java/info/magnolia/ui/actionbar/builder/ActionbarFactoryTest.java delete mode 100644 magnolia-ui-api/src/main/java/info/magnolia/ui/api/ModelConstants.java create mode 100644 magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserPresenterBase.java create mode 100644 magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserSubAppBase.java create mode 100644 magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/beanbrowser/BeanBrowserPresenter.java create mode 100644 magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/beanbrowser/BeanBrowserSubApp.java delete mode 100644 magnolia-ui-vaadin-common-widgets/src/main/java/info/magnolia/ui/vaadin/actionbar/ActionbarView.java create mode 100644 magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/ModelConstants.java create mode 100644 magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/AbstractContentPresenterBase.java create mode 100644 magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/WorkbenchPresenterBase.java create mode 100644 magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/beanworkbench/BeanWorkbenchPresenter.java create mode 100644 magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/list/FSListPresenter.java diff --git a/magnolia-ui-actionbar/pom.xml b/magnolia-ui-actionbar/pom.xml index 4996171..674e8ca 100644 --- a/magnolia-ui-actionbar/pom.xml +++ b/magnolia-ui-actionbar/pom.xml @@ -16,6 +16,11 @@ info.magnolia.ui + magnolia-ui-api + ${project.version} + + + info.magnolia.ui magnolia-ui-vaadin-common-widgets diff --git a/magnolia-ui-actionbar/src/main/java/info/magnolia/ui/actionbar/ActionbarPresenter.java b/magnolia-ui-actionbar/src/main/java/info/magnolia/ui/actionbar/ActionbarPresenter.java index b2036e6..d73a46d 100644 --- a/magnolia-ui-actionbar/src/main/java/info/magnolia/ui/actionbar/ActionbarPresenter.java +++ b/magnolia-ui-actionbar/src/main/java/info/magnolia/ui/actionbar/ActionbarPresenter.java @@ -33,15 +33,20 @@ */ package info.magnolia.ui.actionbar; -import info.magnolia.i18nsystem.SimpleTranslator; -import info.magnolia.objectfactory.Components; -import info.magnolia.ui.actionbar.builder.ActionbarFactory; import info.magnolia.ui.actionbar.definition.ActionbarDefinition; -import info.magnolia.ui.vaadin.actionbar.Actionbar; -import info.magnolia.ui.vaadin.actionbar.ActionbarView; +import info.magnolia.ui.actionbar.definition.ActionbarGroupDefinition; +import info.magnolia.ui.actionbar.definition.ActionbarItemDefinition; +import info.magnolia.ui.actionbar.definition.ActionbarSectionDefinition; +import info.magnolia.ui.api.action.ActionDefinition; +import info.magnolia.ui.vaadin.gwt.client.actionbar.shared.ActionbarItem; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import javax.inject.Inject; +import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -58,35 +63,22 @@ public class ActionbarPresenter implements ActionbarView.Listener { public interface Listener { void onActionbarItemClicked(String itemName); - - String getLabel(String itemName); - - String getIcon(String itemName); - } private static final Logger log = LoggerFactory.getLogger(ActionbarPresenter.class); - private static final String PREVIEW_SECTION_NAME = "preview"; - private ActionbarDefinition definition; - private ActionbarView actionbar; + private Map actions; - private Listener listener; + private ActionbarView view; - private SimpleTranslator translator; + private Listener listener; @Inject - public ActionbarPresenter(SimpleTranslator translator) { - this.translator = translator; - } - - /** - * @deprecated since 5.2.1 - please use {@link #ActionbarPresenter(SimpleTranslator)}. - */ - public ActionbarPresenter() { - this.translator = Components.getComponent(SimpleTranslator.class); + public ActionbarPresenter(ActionbarView view) { + this.view = view; + view.setListener(this); } public void setListener(Listener listener) { @@ -94,83 +86,113 @@ public class ActionbarPresenter implements ActionbarView.Listener { } /** - * Initializes an actionbar with given definition and returns the view for - * parent to add it. + * Initializes an action bar with the given definition and returns the view for the parent to add it. */ - public ActionbarView start(final ActionbarDefinition definition) { + public ActionbarView start(ActionbarDefinition definition, Map actions) { this.definition = definition; - actionbar = ActionbarFactory.build(definition, listener); - actionbar.setListener(this); - return actionbar; - } - - public void setPreview(final Resource previewResource) { - if (previewResource != null) { - if (!((Actionbar) actionbar).getSections().containsKey(PREVIEW_SECTION_NAME)) { - actionbar.addSection(PREVIEW_SECTION_NAME, translator.translate("actionbar.preview")); + this.actions = actions; + + if (definition != null) { + + // build action bar structure from definition + for (ActionbarSectionDefinition section : definition.getSections()) { + view.addSection(section.getName(), section.getLabel()); + List actionNames = new ArrayList(); + + for (ActionbarGroupDefinition group : section.getGroups()) { + // standalone groups make no sense + log.debug("Group actions: " + group.getItems()); + + for (ActionbarItemDefinition action : group.getItems()) { + if (actionNames.contains(action.getName())) { + log.warn("Action was not added: an action with name " + action + "': was already added to the section" + section.getName() + "."); + continue; + } + actionNames.add(action.getName()); + addActionItem(action.getName(), group.getName(), section.getName()); + } + } } - actionbar.setSectionPreview(previewResource, PREVIEW_SECTION_NAME); } else { - if (((Actionbar) actionbar).getSections().containsKey(PREVIEW_SECTION_NAME)) { - actionbar.removeSection(PREVIEW_SECTION_NAME); + log.debug("No actionbar definition found. This will result in an empty action bar. Is that intended?"); + } + return view; + } + + private void addActionItem(String actionName, String groupName, String sectionName) { + + ActionDefinition actionDefinition = actions.get(actionName); + if (actionDefinition != null) { + String label = actionDefinition.getLabel(); + if (StringUtils.isBlank(label)) { + label = actionName; } + String icon = actionDefinition.getIcon(); + + // only icons from icon-fonts currently work + ActionbarItem item = new ActionbarItem(actionName, label, icon, groupName); + view.addAction(item, sectionName); } } + public void setPreview(final Resource previewResource) { + view.setPreview(previewResource); + } + // METHODS DELEGATING TO THE VIEW public void enable(String... actionNames) { - if (actionbar != null) { + if (view != null) { for (String action : actionNames) { - actionbar.setActionEnabled(action, true); + view.setActionEnabled(action, true); } } } public void disable(String... actionNames) { - if (actionbar != null) { + if (view != null) { for (String action : actionNames) { - actionbar.setActionEnabled(action, false); + view.setActionEnabled(action, false); } } } public void enableGroup(String groupName) { - if (actionbar != null) { - actionbar.setGroupEnabled(groupName, true); + if (view != null) { + view.setGroupEnabled(groupName, true); } } public void disableGroup(String groupName) { - if (actionbar != null) { - actionbar.setGroupEnabled(groupName, false); + if (view != null) { + view.setGroupEnabled(groupName, false); } } public void enableGroup(String groupName, String sectionName) { - if (actionbar != null) { - actionbar.setGroupEnabled(groupName, sectionName, true); + if (view != null) { + view.setGroupEnabled(groupName, sectionName, true); } } public void disableGroup(String groupName, String sectionName) { - if (actionbar != null) { - actionbar.setGroupEnabled(groupName, sectionName, false); + if (view != null) { + view.setGroupEnabled(groupName, sectionName, false); } } public void showSection(String... sectionNames) { - if (actionbar != null) { + if (view != null) { for (String section : sectionNames) { - actionbar.setSectionVisible(section, true); + view.setSectionVisible(section, true); } } } public void hideSection(String... sectionNames) { - if (actionbar != null) { + if (view != null) { for (String section : sectionNames) { - actionbar.setSectionVisible(section, false); + view.setSectionVisible(section, false); } } } diff --git a/magnolia-ui-actionbar/src/main/java/info/magnolia/ui/actionbar/ActionbarView.java b/magnolia-ui-actionbar/src/main/java/info/magnolia/ui/actionbar/ActionbarView.java new file mode 100644 index 0000000..d77f8c4 --- /dev/null +++ b/magnolia-ui-actionbar/src/main/java/info/magnolia/ui/actionbar/ActionbarView.java @@ -0,0 +1,87 @@ +/** + * This file Copyright (c) 2012-2013 Magnolia International + * Ltd. (http://www.magnolia-cms.com). All rights reserved. + * + * + * This file is dual-licensed under both the Magnolia + * Network Agreement and the GNU General Public License. + * You may elect to use one or the other of these licenses. + * + * This file is distributed in the hope that it will be + * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. + * Redistribution, except as permitted by whichever of the GPL + * or MNA you select, is prohibited. + * + * 1. For the GPL license (GPL), you can redistribute and/or + * modify this file under the terms of the GNU General + * Public License, Version 3, as published by the Free Software + * Foundation. You should have received a copy of the GNU + * General Public License, Version 3 along with this program; + * if not, write to the Free Software Foundation, Inc., 51 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 2. For the Magnolia Network Agreement (MNA), this file + * and the accompanying materials are made available under the + * terms of the MNA which accompanies this distribution, and + * is available at http://www.magnolia-cms.com/mna.html + * + * Any modifications to this file must keep this entire header + * intact. + * + */ +package info.magnolia.ui.actionbar; + +import info.magnolia.ui.api.view.View; +import info.magnolia.ui.vaadin.gwt.client.actionbar.shared.ActionbarItem; + +import com.vaadin.server.Resource; + +/** + * Base interface for an action bar view. + */ +public interface ActionbarView extends View { + + void setListener(Listener listener); + + void addSection(String sectionName, String label); + + void removeSection(String sectionName); + + void setPreview(final Resource previewResource); + + void addAction(ActionbarItem action, String sectionName); + + void removeAction(String actionName); + + + // ENABLE / DISABLE + void setActionEnabled(String actionName, boolean isEnabled); + + void setActionEnabled(String actionName, String sectionName, boolean isEnabled); + + void setGroupEnabled(String groupName, boolean isEnabled); + + void setGroupEnabled(String groupName, String sectionName, boolean isEnabled); + + // SHOW / HIDE SECTIONS + void setSectionVisible(String sectionName, boolean isVisible); + + boolean isSectionVisible(String sectionName); + + void setOpen(boolean isOpen); + + /** + * Base interface for an action bar listener. + */ + interface Listener { + + /** + * Event handler invoked on clicking an item in the action bar. + * + * @param actionToken the action token + */ + void onActionbarItemClicked(String actionToken); + } +} \ No newline at end of file diff --git a/magnolia-ui-actionbar/src/main/java/info/magnolia/ui/actionbar/ActionbarViewImpl.java b/magnolia-ui-actionbar/src/main/java/info/magnolia/ui/actionbar/ActionbarViewImpl.java new file mode 100644 index 0000000..484f37e --- /dev/null +++ b/magnolia-ui-actionbar/src/main/java/info/magnolia/ui/actionbar/ActionbarViewImpl.java @@ -0,0 +1,153 @@ +/** + * This file Copyright (c) 2013 Magnolia International + * Ltd. (http://www.magnolia-cms.com). All rights reserved. + * + * + * This file is dual-licensed under both the Magnolia + * Network Agreement and the GNU General Public License. + * You may elect to use one or the other of these licenses. + * + * This file is distributed in the hope that it will be + * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. + * Redistribution, except as permitted by whichever of the GPL + * or MNA you select, is prohibited. + * + * 1. For the GPL license (GPL), you can redistribute and/or + * modify this file under the terms of the GNU General + * Public License, Version 3, as published by the Free Software + * Foundation. You should have received a copy of the GNU + * General Public License, Version 3 along with this program; + * if not, write to the Free Software Foundation, Inc., 51 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 2. For the Magnolia Network Agreement (MNA), this file + * and the accompanying materials are made available under the + * terms of the MNA which accompanies this distribution, and + * is available at http://www.magnolia-cms.com/mna.html + * + * Any modifications to this file must keep this entire header + * intact. + * + */ +package info.magnolia.ui.actionbar; + +import info.magnolia.i18nsystem.SimpleTranslator; +import info.magnolia.ui.vaadin.actionbar.Actionbar; +import info.magnolia.ui.vaadin.actionbar.Actionbar.ActionTriggerEvent; +import info.magnolia.ui.vaadin.actionbar.Actionbar.ActionTriggerListener; +import info.magnolia.ui.vaadin.gwt.client.actionbar.shared.ActionbarItem; + +import javax.inject.Inject; + +import com.vaadin.server.Resource; + +/** + * Default Vaadin implementation of the action bar view. + */ +public class ActionbarViewImpl implements ActionbarView { + + private static final String PREVIEW_SECTION_NAME = "preview"; + + private Actionbar actionBar = new Actionbar(); + + private ActionbarView.Listener listener; + + private SimpleTranslator i18n; + + @Inject + public ActionbarViewImpl(SimpleTranslator i18n) { + this.i18n = i18n; + actionBar.addActionTriggerListener(new ActionTriggerListener() { + + @Override + public void actionTrigger(ActionTriggerEvent event) { + if (listener != null) { + listener.onActionbarItemClicked(event.getActionName()); + } + } + }); + } + + @Override + public void setListener(Listener listener) { + this.listener = listener; + } + + @Override + public void addSection(String sectionName, String label) { + actionBar.addSection(sectionName, label); + } + + @Override + public void removeSection(String sectionName) { + actionBar.removeSection(sectionName); + } + + @Override + public void setPreview(Resource previewResource) { + if (previewResource != null) { + if (!actionBar.getSections().containsKey(PREVIEW_SECTION_NAME)) { + actionBar.addSection(PREVIEW_SECTION_NAME, i18n.translate("actionbar.preview")); + + } + actionBar.setSectionPreview(previewResource, PREVIEW_SECTION_NAME); + } else { + if (actionBar.getSections().containsKey(PREVIEW_SECTION_NAME)) { + actionBar.removeSection(PREVIEW_SECTION_NAME); + } + } + } + + @Override + public void addAction(ActionbarItem action, String sectionName) { + actionBar.addAction(action, sectionName); + } + + @Override + public void removeAction(String actionName) { + actionBar.removeAction(actionName); + } + + @Override + public void setActionEnabled(String actionName, boolean isEnabled) { + actionBar.setActionEnabled(actionName, isEnabled); + } + + @Override + public void setActionEnabled(String actionName, String sectionName, boolean isEnabled) { + actionBar.setActionEnabled(sectionName, actionName, isEnabled); + } + + @Override + public void setGroupEnabled(String groupName, boolean isEnabled) { + actionBar.setGroupEnabled(groupName, isEnabled); + } + + @Override + public void setGroupEnabled(String groupName, String sectionName, boolean isEnabled) { + actionBar.setGroupEnabled(groupName, sectionName, isEnabled); + } + + @Override + public void setSectionVisible(String sectionName, boolean isVisible) { + actionBar.setSectionVisible(sectionName, isVisible); + } + + @Override + public boolean isSectionVisible(String sectionName) { + return actionBar.isSectionVisible(sectionName); + } + + @Override + public void setOpen(boolean isOpen) { + actionBar.setOpen(isOpen); + } + + @Override + public Actionbar asVaadinComponent() { + return actionBar; + } + +} diff --git a/magnolia-ui-actionbar/src/main/java/info/magnolia/ui/actionbar/builder/ActionbarFactory.java b/magnolia-ui-actionbar/src/main/java/info/magnolia/ui/actionbar/builder/ActionbarFactory.java deleted file mode 100644 index aec841c..0000000 --- a/magnolia-ui-actionbar/src/main/java/info/magnolia/ui/actionbar/builder/ActionbarFactory.java +++ /dev/null @@ -1,114 +0,0 @@ -/** - * This file Copyright (c) 2012-2013 Magnolia International - * Ltd. (http://www.magnolia-cms.com). All rights reserved. - * - * - * This file is dual-licensed under both the Magnolia - * Network Agreement and the GNU General Public License. - * You may elect to use one or the other of these licenses. - * - * This file is distributed in the hope that it will be - * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. - * Redistribution, except as permitted by whichever of the GPL - * or MNA you select, is prohibited. - * - * 1. For the GPL license (GPL), you can redistribute and/or - * modify this file under the terms of the GNU General - * Public License, Version 3, as published by the Free Software - * Foundation. You should have received a copy of the GNU - * General Public License, Version 3 along with this program; - * if not, write to the Free Software Foundation, Inc., 51 - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * 2. For the Magnolia Network Agreement (MNA), this file - * and the accompanying materials are made available under the - * terms of the MNA which accompanies this distribution, and - * is available at http://www.magnolia-cms.com/mna.html - * - * Any modifications to this file must keep this entire header - * intact. - * - */ -package info.magnolia.ui.actionbar.builder; - -import info.magnolia.ui.actionbar.ActionbarPresenter; -import info.magnolia.ui.actionbar.definition.ActionbarDefinition; -import info.magnolia.ui.actionbar.definition.ActionbarGroupDefinition; -import info.magnolia.ui.actionbar.definition.ActionbarItemDefinition; -import info.magnolia.ui.actionbar.definition.ActionbarSectionDefinition; -import info.magnolia.ui.vaadin.actionbar.Actionbar; -import info.magnolia.ui.vaadin.actionbar.ActionbarView; -import info.magnolia.ui.vaadin.gwt.client.actionbar.shared.ActionbarItem; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.vaadin.server.ThemeResource; - -/** - * Basic builder for an action bar widget based on an action bar definition. - */ -public class ActionbarFactory { - - private static final Logger log = LoggerFactory.getLogger(ActionbarFactory.class); - - public static ActionbarView build(ActionbarDefinition definition, ActionbarPresenter.Listener listener) { - Actionbar actionbar = new Actionbar(); - if (definition == null) { - log.debug("No actionbar definition found. This will result in an empty action bar. Is that intended?"); - return actionbar; - } else { - - for (ActionbarSectionDefinition section : definition.getSections()) { - actionbar.addSection(section.getName(), section.getLabel()); - List actionNames = new ArrayList(); - for (ActionbarGroupDefinition group : section.getGroups()) { - // standalone groups make no sense - log.debug("Group actions: " + group.getItems()); - for (ActionbarItemDefinition action : group.getItems()) { - - if (actionNames.contains(action.getName())) { - log.warn("Action was not added: an action with name " + action + "': was already added to the section" + section.getName() + "."); - continue; - } - - actionNames.add(action.getName()); - addItemFromDefinition(listener, actionbar, group.getName(), section.getName(), action.getName()); - } - } - } - } - return actionbar; - } - - public static void addItemFromDefinition(ActionbarPresenter.Listener listener, Actionbar actionBar, String groupName, String sectionName, String actionName) { - ActionbarItem entry; - String icon = listener.getIcon(actionName); - String label = listener.getLabel(actionName); - if (StringUtils.isBlank(label)) { - return; - } - if (StringUtils.isNotBlank(icon)) { - if (icon.startsWith("icon-")) { - entry = new ActionbarItem(actionName, label, icon, groupName); - } else { - try { - actionBar.registerActionIconResource(actionName, new ThemeResource(icon)); - } catch (NullPointerException e) { - log.warn("Icon resource not found for Actionbar item " + actionName + "'."); - } finally { - entry = new ActionbarItem(actionName, label, null, groupName); - } - } - } else { - entry = new ActionbarItem(actionName, label, null, groupName); - } - actionBar.addAction(entry, sectionName); - } -} diff --git a/magnolia-ui-actionbar/src/test/java/info/magnolia/ui/actionbar/ActionbarPresenterTest.java b/magnolia-ui-actionbar/src/test/java/info/magnolia/ui/actionbar/ActionbarPresenterTest.java new file mode 100644 index 0000000..da6264f --- /dev/null +++ b/magnolia-ui-actionbar/src/test/java/info/magnolia/ui/actionbar/ActionbarPresenterTest.java @@ -0,0 +1,274 @@ +/** + * This file Copyright (c) 2012-2013 Magnolia International + * Ltd. (http://www.magnolia-cms.com). All rights reserved. + * + * + * This file is dual-licensed under both the Magnolia + * Network Agreement and the GNU General Public License. + * You may elect to use one or the other of these licenses. + * + * This file is distributed in the hope that it will be + * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. + * Redistribution, except as permitted by whichever of the GPL + * or MNA you select, is prohibited. + * + * 1. For the GPL license (GPL), you can redistribute and/or + * modify this file under the terms of the GNU General + * Public License, Version 3, as published by the Free Software + * Foundation. You should have received a copy of the GNU + * General Public License, Version 3 along with this program; + * if not, write to the Free Software Foundation, Inc., 51 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 2. For the Magnolia Network Agreement (MNA), this file + * and the accompanying materials are made available under the + * terms of the MNA which accompanies this distribution, and + * is available at http://www.magnolia-cms.com/mna.html + * + * Any modifications to this file must keep this entire header + * intact. + * + */ +package info.magnolia.ui.actionbar; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; + +import info.magnolia.i18nsystem.SimpleTranslator; +import info.magnolia.objectfactory.Components; +import info.magnolia.test.ComponentsTestUtil; +import info.magnolia.ui.actionbar.definition.ActionbarDefinition; +import info.magnolia.ui.actionbar.definition.ActionbarGroupDefinition; +import info.magnolia.ui.actionbar.definition.ActionbarItemDefinition; +import info.magnolia.ui.actionbar.definition.ActionbarSectionDefinition; +import info.magnolia.ui.actionbar.definition.ConfiguredActionbarDefinition; +import info.magnolia.ui.actionbar.definition.ConfiguredActionbarGroupDefinition; +import info.magnolia.ui.actionbar.definition.ConfiguredActionbarItemDefinition; +import info.magnolia.ui.actionbar.definition.ConfiguredActionbarSectionDefinition; +import info.magnolia.ui.api.action.ActionDefinition; +import info.magnolia.ui.api.action.ConfiguredActionDefinition; +import info.magnolia.ui.api.availability.AvailabilityDefinition; +import info.magnolia.ui.api.availability.ConfiguredAvailabilityDefinition; +import info.magnolia.ui.vaadin.actionbar.Actionbar; +import info.magnolia.ui.vaadin.gwt.client.actionbar.shared.ActionbarItem; +import info.magnolia.ui.vaadin.gwt.client.actionbar.shared.ActionbarSection; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; + +/** + * Tests for the ActionbarPresenter. + */ +public class ActionbarPresenterTest { + + private static final String SECTION_ASSETS = "assets"; + private static final String SECTION_BOOKS = "books"; + + private static final String ACTION_ASSET_ADD = "addAsset"; + private static final String ACTION_ASSET_DELETE = "deleteAsset"; + private static final String ACTION_ASSET_EDIT = "editAsset"; + + private static final String ACTION_BOOK_ADD = "addBook"; + private static final String ACTION_BOOK_DELETE = "deleteBook"; + private static final String ACTION_BOOK_EDIT = "editBook"; + + + private ActionbarPresenter presenter; + + private ActionbarDefinition definition; + private Map actions = new HashMap(); + + @Before + public void setUp() throws Exception { + ComponentsTestUtil.setImplementation(AvailabilityDefinition.class, ConfiguredAvailabilityDefinition.class); + ComponentsTestUtil.setImplementation(ActionbarView.class, ActionbarViewImpl.class); + ComponentsTestUtil.setInstance(SimpleTranslator.class, mock(SimpleTranslator.class)); + presenter = Components.newInstance(ActionbarPresenter.class); + definition = initDefinitions(); + } + + @Test + public void testBuildingActionbar() { + + // GIVEN + ActionbarSectionDefinition sectionA = definition.getSections().get(0); + ActionbarSectionDefinition sectionB = definition.getSections().get(1); + int countA = getActionsCount(sectionA); + int countB = getActionsCount(sectionB); + + // WHEN + ActionbarView view = presenter.start(definition, actions); + + // THEN + Actionbar actionbar = ((ActionbarViewImpl) view).asVaadinComponent(); + Map sections = actionbar.getSections(); + assertEquals(definition.getSections().size(), sections.size()); + assertEquals(sectionA.getName(), sections.get(SECTION_ASSETS).getName()); + assertEquals(sectionB.getName(), sections.get(SECTION_BOOKS).getName()); + + Map aActions = sections.get(SECTION_ASSETS).getActions(); + assertEquals(countA, aActions.size()); + assertTrue(aActions.containsKey(ACTION_ASSET_ADD)); + assertTrue(aActions.containsKey(ACTION_ASSET_DELETE)); + assertTrue(aActions.containsKey(ACTION_ASSET_EDIT)); + + Map actionsB = sections.get(SECTION_BOOKS).getActions(); + assertEquals(countB, actionsB.size()); + assertTrue(actionsB.containsKey(ACTION_BOOK_ADD)); + assertTrue(actionsB.containsKey(ACTION_BOOK_DELETE)); + assertTrue(actionsB.containsKey(ACTION_BOOK_EDIT)); + } + + @Test + public void testBuildingActionbarWithEmptyGroup() { + // GIVEN + final String emptyGroupName = "2"; + ActionbarSectionDefinition section = definition.getSections().get(0); + ((ConfiguredActionbarSectionDefinition) section).addGroup(new ConfiguredActionbarGroupDefinition() { + { + setName(emptyGroupName); + } + }); + + int count = getActionsCount(section); + + // WHEN + ActionbarView view = presenter.start(definition, actions); + + // THEN + Actionbar actionbar = ((ActionbarViewImpl) view).asVaadinComponent(); + Map actions = actionbar.getSections().get(SECTION_ASSETS).getActions(); + assertEquals(count, actions.size()); + for (ActionbarItem action : actions.values()) { + assertNotEquals(emptyGroupName, action.getGroupName()); + } + } + + @Test + public void testBuildingActionbarWithDuplicateAction() { + // GIVEN + final String duplicateActionName = ACTION_ASSET_ADD; + + // duplicate in same group + ActionbarSectionDefinition sectionA = definition.getSections().get(0); + ActionbarGroupDefinition groupA0 = sectionA.getGroups().get(0); + ((ConfiguredActionbarGroupDefinition) groupA0).addItem(new ConfiguredActionbarItemDefinition() { + { + setName(duplicateActionName); + } + }); + + // duplicate in same section but different group + ActionbarGroupDefinition groupA1 = sectionA.getGroups().get(1); + ((ConfiguredActionbarGroupDefinition) groupA1).addItem(new ConfiguredActionbarItemDefinition() { + { + setName(duplicateActionName); + } + }); + + // duplicate in different section + ActionbarSectionDefinition sectionB = definition.getSections().get(1); + ActionbarGroupDefinition groupB0 = sectionB.getGroups().get(0); + ((ConfiguredActionbarGroupDefinition) groupB0).addItem(new ConfiguredActionbarItemDefinition() { + { + setName(duplicateActionName); + } + }); + + int countA = getActionsCount(sectionA); + int countB = getActionsCount(sectionB); + + // WHEN + ActionbarView view = presenter.start(definition, actions); + + // THEN + Actionbar actionbar = ((ActionbarViewImpl) view).asVaadinComponent(); + Map actionsA = actionbar.getSections().get(SECTION_ASSETS).getActions(); + Map actionsB = actionbar.getSections().get(SECTION_BOOKS).getActions(); + + // same section duplicates shouldn't be added, but duplicate in different section should + assertEquals(countA - 2, actionsA.size()); + assertEquals(countB, actionsB.size()); + assertTrue(actionsA.containsKey(ACTION_ASSET_ADD)); + assertTrue(actionsA.containsKey(ACTION_ASSET_DELETE)); + assertTrue(actionsA.containsKey(ACTION_ASSET_EDIT)); + assertTrue(actionsB.containsKey(duplicateActionName)); + + } + + /** + * Builds an actionbar definition consisiting of two sections with two groups each, one for adding/deleting actions, one for editing actions. + */ + private ActionbarDefinition initDefinitions() { + return new ConfiguredActionbarDefinition() { + { + addSection(new ConfiguredActionbarSectionDefinition() { + { + setName(SECTION_ASSETS); + addGroup(new ConfiguredActionbarGroupDefinition() { + { + setName("0"); + addItem(initAction(ACTION_ASSET_ADD)); + addItem(initAction(ACTION_ASSET_DELETE)); + } + }); + addGroup(new ConfiguredActionbarGroupDefinition() { + { + setName("1"); + addItem(initAction(ACTION_ASSET_EDIT)); + } + }); + } + }); + addSection(new ConfiguredActionbarSectionDefinition() { + { + setName(SECTION_BOOKS); + addGroup(new ConfiguredActionbarGroupDefinition() { + { + setName("0"); + addItem(initAction(ACTION_BOOK_ADD)); + addItem(initAction(ACTION_BOOK_DELETE)); + } + }); + addGroup(new ConfiguredActionbarGroupDefinition() { + { + setName("1"); + addItem(initAction(ACTION_BOOK_EDIT)); + } + }); + } + }); + } + }; + } + + /** + * Builds an action bar item and registers an action definition with the same name. + */ + private ActionbarItemDefinition initAction(final String actionName) { + actions.put(actionName, new ConfiguredActionDefinition() { + { + setName(actionName); + } + }); + return new ConfiguredActionbarItemDefinition() { + { + setName(actionName); + } + }; + } + + private int getActionsCount(ActionbarSectionDefinition section) { + int count = 0; + for (ActionbarGroupDefinition group : section.getGroups()) { + count += group.getItems().size(); + } + return count; + } + +} diff --git a/magnolia-ui-actionbar/src/test/java/info/magnolia/ui/actionbar/builder/ActionbarFactoryTest.java b/magnolia-ui-actionbar/src/test/java/info/magnolia/ui/actionbar/builder/ActionbarFactoryTest.java deleted file mode 100644 index 0b6dceb..0000000 --- a/magnolia-ui-actionbar/src/test/java/info/magnolia/ui/actionbar/builder/ActionbarFactoryTest.java +++ /dev/null @@ -1,295 +0,0 @@ -/** - * This file Copyright (c) 2012-2013 Magnolia International - * Ltd. (http://www.magnolia-cms.com). All rights reserved. - * - * - * This file is dual-licensed under both the Magnolia - * Network Agreement and the GNU General Public License. - * You may elect to use one or the other of these licenses. - * - * This file is distributed in the hope that it will be - * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. - * Redistribution, except as permitted by whichever of the GPL - * or MNA you select, is prohibited. - * - * 1. For the GPL license (GPL), you can redistribute and/or - * modify this file under the terms of the GNU General - * Public License, Version 3, as published by the Free Software - * Foundation. You should have received a copy of the GNU - * General Public License, Version 3 along with this program; - * if not, write to the Free Software Foundation, Inc., 51 - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * 2. For the Magnolia Network Agreement (MNA), this file - * and the accompanying materials are made available under the - * terms of the MNA which accompanies this distribution, and - * is available at http://www.magnolia-cms.com/mna.html - * - * Any modifications to this file must keep this entire header - * intact. - * - */ -package info.magnolia.ui.actionbar.builder; - -import static org.junit.Assert.*; - -import info.magnolia.test.ComponentsTestUtil; -import info.magnolia.test.MgnlTestCase; -import info.magnolia.ui.actionbar.ActionbarPresenter; -import info.magnolia.ui.actionbar.definition.ActionbarGroupDefinition; -import info.magnolia.ui.actionbar.definition.ActionbarSectionDefinition; -import info.magnolia.ui.actionbar.definition.ConfiguredActionbarDefinition; -import info.magnolia.ui.actionbar.definition.ConfiguredActionbarGroupDefinition; -import info.magnolia.ui.actionbar.definition.ConfiguredActionbarItemDefinition; -import info.magnolia.ui.actionbar.definition.ConfiguredActionbarSectionDefinition; -import info.magnolia.ui.api.action.ActionDefinition; -import info.magnolia.ui.api.action.ConfiguredActionDefinition; -import info.magnolia.ui.api.availability.AvailabilityDefinition; -import info.magnolia.ui.api.availability.ConfiguredAvailabilityDefinition; -import info.magnolia.ui.vaadin.actionbar.Actionbar; -import info.magnolia.ui.vaadin.actionbar.ActionbarView; -import info.magnolia.ui.vaadin.gwt.client.actionbar.shared.ActionbarItem; -import info.magnolia.ui.vaadin.gwt.client.actionbar.shared.ActionbarSection; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang.StringUtils; -import org.junit.Before; -import org.junit.Test; - -/** - * Tests for the ActionbarFactory. - */ -public class ActionbarFactoryTest extends MgnlTestCase { - - private static final String SECTION_A = "sectionA"; - - private static final String SECTION_B = "sectionB"; - - @Before - @Override - public void setUp() throws Exception { - super.setUp(); - ComponentsTestUtil.setImplementation(AvailabilityDefinition.class, ConfiguredAvailabilityDefinition.class); - } - - @Test - public void testBuildingActionbar() { - - // GIVEN - Map actionDefs = new HashMap(); - actionDefs.put("0.0", new TestActionDefinition("0.0")); - actionDefs.put("1.0", new TestActionDefinition("1.0")); - actionDefs.put("1.1", new TestActionDefinition("1.1")); - actionDefs.put("2.0", new TestActionDefinition("2.0")); - - final ConfiguredActionbarDefinition def = new ConfiguredActionbarDefinition(); - - // common group - ActionbarGroupDefinition previewGroup = buildGroup("0", - "0.0"); - - // sections - ActionbarSectionDefinition aSection = buildSection(SECTION_A, - previewGroup, - buildGroup("1", - "1.0", - "1.1")); - ActionbarSectionDefinition bSection = buildSection(SECTION_B, - previewGroup, - buildGroup("1", - "1.0", - "1.1"), - buildGroup("2", - "2.0")); - - def.addSection(aSection); - def.addSection(bSection); - - ActionbarListener listener = new ActionbarListener(actionDefs); - - // test variables - int aActionCount = getActionsCount(aSection); - int bActionCount = getActionsCount(bSection); - - // WHEN - ActionbarView actionbar = ActionbarFactory.build(def, listener); - - // THEN - Map sections = ((Actionbar) actionbar).getSections(); - assertEquals(def.getSections().size(), sections.size()); - assertEquals(aSection.getName(), sections.get(SECTION_A).getName()); - assertEquals(bSection.getName(), sections.get(SECTION_B).getName()); - - Map aActions = sections.get(SECTION_A).getActions(); - assertEquals(aActionCount, aActions.size()); - assertTrue(aActions.containsKey("0.0")); - assertTrue(aActions.containsKey("1.1")); - - Map bActions = sections.get(SECTION_B).getActions(); - assertEquals(bActionCount, bActions.size()); - assertTrue(bActions.containsKey("0.0")); - assertTrue(bActions.containsKey("1.0")); - assertTrue(bActions.containsKey("2.0")); - } - - @Test - public void testBuildingActionbarWithEmptyGroup() { - // GIVEN - Map actionDefs = new HashMap(); - actionDefs.put("1.0", new TestActionDefinition("1.0")); - actionDefs.put("1.1", new TestActionDefinition("1.1")); - ConfiguredActionbarDefinition def = new ConfiguredActionbarDefinition(); - ActionbarSectionDefinition sectionDef = buildSection(SECTION_A, - buildGroup("0"), - buildGroup("1", - "1.0", - "1.1")); - def.addSection(sectionDef); - int actionCount = getActionsCount(sectionDef); - - ActionbarListener listener = new ActionbarListener(actionDefs); - - // WHEN - ActionbarView actionbar = ActionbarFactory.build(def, listener); - - // THEN - Map actions = ((Actionbar) actionbar).getSections().get(SECTION_A).getActions(); - assertEquals(actionCount, actions.size()); - for (ActionbarItem action : actions.values()) { - assertTrue(action.getGroupName() != "0"); - } - } - - private static class TestActionDefinition extends ConfiguredActionDefinition { - - public TestActionDefinition(String id) { - setName(id); - setIcon("test"); - setDescription(""); - setI18nBasename(""); - setImplementationClass(null); - setLabel("label"); - } - } - - @Test - public void testBuildingActionbarWithDuplicateAction() { - // GIVEN - Map actionDefs = new HashMap(); - actionDefs.put("0.0", new TestActionDefinition("0.0")); - actionDefs.put("0.1", new TestActionDefinition("0.1")); - actionDefs.put("0.2", new TestActionDefinition("0.2")); - actionDefs.put("0.3", new TestActionDefinition("0.3")); - actionDefs.put("1.0", new TestActionDefinition("1.0")); - - ConfiguredActionbarDefinition def = new ConfiguredActionbarDefinition(); - ActionbarSectionDefinition aSection = buildSection(SECTION_A, - buildGroup("0", - "0.0", - "0.1", - "0.1", - "0.2", - "0.3"), - buildGroup("1", - "1.0", - "0.2")); - ActionbarSectionDefinition bSection = buildSection(SECTION_B, - buildGroup("0", - "0.3")); - def.addSection(aSection); - def.addSection(bSection); - - ActionbarListener listener = new ActionbarListener(actionDefs); - - // test variables - int aActionCount = getActionsCount(aSection); - int bActionCount = getActionsCount(bSection); - - - // WHEN - ActionbarView actionbar = ActionbarFactory.build(def, listener); - - // THEN - Map aActions = ((Actionbar) actionbar).getSections().get(SECTION_A).getActions(); - Map bActions = ((Actionbar) actionbar).getSections().get(SECTION_B).getActions(); - // duplicates 0.1 and 0.2 shouldn't be added, but duplicate 0.3 should - assertEquals(aActionCount - 2, aActions.size()); - assertEquals(bActionCount, bActions.size()); - assertTrue(aActions.containsKey("0.1")); - assertTrue(aActions.containsKey("0.2")); - assertTrue(aActions.containsKey("0.3")); - assertTrue(bActions.containsKey("0.3")); - - } - - private ActionbarSectionDefinition buildSection(String name, ActionbarGroupDefinition... groups) { - ConfiguredActionbarSectionDefinition section = new ConfiguredActionbarSectionDefinition(); - section.setName(name); - for (ActionbarGroupDefinition group : groups) { - section.addGroup(group); - } - return section; - } - - private ActionbarGroupDefinition buildGroup(String name, String...actions) { - ConfiguredActionbarGroupDefinition group = new ConfiguredActionbarGroupDefinition(); - group.setName(name); - for (String action : actions) { - ConfiguredActionbarItemDefinition def = new ConfiguredActionbarItemDefinition(); - def.setName(action); - group.addItem(def); - } - return group; - } - - private int getActionsCount(ActionbarSectionDefinition section) { - int count = 0; - for (ActionbarGroupDefinition group : section.getGroups()) { - count += group.getItems().size(); - } - return count; - } - - private boolean containsAction(List actions, String actionName) { - Iterator iterator = actions.iterator(); - while (iterator.hasNext()) { - ActionbarItem action = iterator.next(); - if (StringUtils.equals(action.getName(), actionName)) { - return true; - } - } - return false; - } - - private class ActionbarListener implements ActionbarPresenter.Listener { - - private Map actionDefinitions; - - private ActionbarListener(Map actionDefinitions) { - this.actionDefinitions = actionDefinitions; - } - - @Override - public void onActionbarItemClicked(String actionName) { - - } - - @Override - public String getLabel(String actionName) { - return actionDefinitions.get(actionName).getLabel(); - } - - @Override - public String getIcon(String actionName) { - return actionDefinitions.get(actionName).getLabel(); - } - - } - -} diff --git a/magnolia-ui-admincentral/src/main/java/info/magnolia/ui/admincentral/dialog/action/SaveDialogAction.java b/magnolia-ui-admincentral/src/main/java/info/magnolia/ui/admincentral/dialog/action/SaveDialogAction.java index 1249e59..a2205af 100644 --- a/magnolia-ui-admincentral/src/main/java/info/magnolia/ui/admincentral/dialog/action/SaveDialogAction.java +++ b/magnolia-ui-admincentral/src/main/java/info/magnolia/ui/admincentral/dialog/action/SaveDialogAction.java @@ -35,7 +35,7 @@ package info.magnolia.ui.admincentral.dialog.action; import info.magnolia.cms.core.Path; import info.magnolia.jcr.util.NodeUtil; -import info.magnolia.ui.api.ModelConstants; +import info.magnolia.ui.vaadin.integration.jcr.ModelConstants; import info.magnolia.ui.api.action.AbstractAction; import info.magnolia.ui.api.action.ActionExecutionException; import info.magnolia.ui.form.EditorCallback; diff --git a/magnolia-ui-admincentral/src/main/java/info/magnolia/ui/admincentral/shellapp/favorites/FavoritesManagerImpl.java b/magnolia-ui-admincentral/src/main/java/info/magnolia/ui/admincentral/shellapp/favorites/FavoritesManagerImpl.java index 4a4f44d..bfa2a64 100644 --- a/magnolia-ui-admincentral/src/main/java/info/magnolia/ui/admincentral/shellapp/favorites/FavoritesManagerImpl.java +++ b/magnolia-ui-admincentral/src/main/java/info/magnolia/ui/admincentral/shellapp/favorites/FavoritesManagerImpl.java @@ -39,7 +39,7 @@ import info.magnolia.context.MgnlContext; import info.magnolia.jcr.RuntimeRepositoryException; import info.magnolia.jcr.util.NodeUtil; import info.magnolia.jcr.util.PropertyUtil; -import info.magnolia.ui.api.ModelConstants; +import info.magnolia.ui.vaadin.integration.jcr.ModelConstants; import info.magnolia.ui.framework.AdmincentralNodeTypes; import info.magnolia.ui.framework.favorite.FavoriteStore; import info.magnolia.ui.vaadin.integration.jcr.AbstractJcrNodeAdapter; diff --git a/magnolia-ui-admincentral/src/main/java/info/magnolia/ui/admincentral/shellapp/pulse/message/MessagePresenter.java b/magnolia-ui-admincentral/src/main/java/info/magnolia/ui/admincentral/shellapp/pulse/message/MessagePresenter.java index 8a0f76a..a74d5e1 100644 --- a/magnolia-ui-admincentral/src/main/java/info/magnolia/ui/admincentral/shellapp/pulse/message/MessagePresenter.java +++ b/magnolia-ui-admincentral/src/main/java/info/magnolia/ui/admincentral/shellapp/pulse/message/MessagePresenter.java @@ -33,7 +33,6 @@ */ package info.magnolia.ui.admincentral.shellapp.pulse.message; -import com.vaadin.data.util.BeanItem; import info.magnolia.context.MgnlContext; import info.magnolia.i18nsystem.I18nizer; import info.magnolia.registry.RegistrationException; @@ -46,10 +45,13 @@ import info.magnolia.ui.api.message.Message; import info.magnolia.ui.api.view.View; import info.magnolia.ui.dialog.formdialog.FormBuilder; import info.magnolia.ui.framework.message.MessagesManager; -import org.apache.commons.lang.StringUtils; import javax.inject.Inject; +import org.apache.commons.lang.StringUtils; + +import com.vaadin.data.util.BeanItem; + /** * MessagePresenter. */ @@ -97,7 +99,7 @@ public final class MessagePresenter implements MessageView.Listener, ActionbarPr View mView = formbuilder.buildView(messageViewDefinition.getForm(), messageItem); view.setMessageView(mView); - view.setActionbarView(actionbarPresenter.start(messageViewDefinition.getActionbar())); + view.setActionbarView(actionbarPresenter.start(messageViewDefinition.getActionbar(), messageViewDefinition.getActions())); } catch (RegistrationException e) { throw new RuntimeException("Could not retrieve messageView for " + messageView, e); } @@ -123,17 +125,6 @@ public final class MessagePresenter implements MessageView.Listener, ActionbarPr } } - @Override - public String getLabel(String actionName) { - return messageActionExecutor.getActionDefinition(actionName).getLabel(); - } - - @Override - public String getIcon(String actionName) { - return messageActionExecutor.getActionDefinition(actionName).getIcon(); - } - - /** * Listener interface used to call back to parent presenter. */ diff --git a/magnolia-ui-admincentral/src/main/resources/META-INF/magnolia/ui-admincentral.xml b/magnolia-ui-admincentral/src/main/resources/META-INF/magnolia/ui-admincentral.xml index e3a3f09..be5d452 100644 --- a/magnolia-ui-admincentral/src/main/resources/META-INF/magnolia/ui-admincentral.xml +++ b/magnolia-ui-admincentral/src/main/resources/META-INF/magnolia/ui-admincentral.xml @@ -72,6 +72,14 @@ info.magnolia.ui.admincentral.AdmincentralPresenter + info.magnolia.ui.actionbar.ActionbarPresenter + info.magnolia.ui.actionbar.ActionbarPresenter + + + info.magnolia.ui.actionbar.ActionbarView + info.magnolia.ui.actionbar.ActionbarViewImpl + + info.magnolia.ui.admincentral.shellapp.pulse.message.PulseMessagesPresenter info.magnolia.ui.admincentral.shellapp.pulse.message.PulseMessagesPresenter diff --git a/magnolia-ui-api/pom.xml b/magnolia-ui-api/pom.xml index 34dd0be..a3f7f37 100644 --- a/magnolia-ui-api/pom.xml +++ b/magnolia-ui-api/pom.xml @@ -41,6 +41,10 @@ vaadin-server + info.magnolia.ui + magnolia-ui-vaadin-integration + + junit junit diff --git a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/ModelConstants.java b/magnolia-ui-api/src/main/java/info/magnolia/ui/api/ModelConstants.java deleted file mode 100644 index 0475757..0000000 --- a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/ModelConstants.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * This file Copyright (c) 2012-2013 Magnolia International - * Ltd. (http://www.magnolia-cms.com). All rights reserved. - * - * - * This file is dual-licensed under both the Magnolia - * Network Agreement and the GNU General Public License. - * You may elect to use one or the other of these licenses. - * - * This file is distributed in the hope that it will be - * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. - * Redistribution, except as permitted by whichever of the GPL - * or MNA you select, is prohibited. - * - * 1. For the GPL license (GPL), you can redistribute and/or - * modify this file under the terms of the GNU General - * Public License, Version 3, as published by the Free Software - * Foundation. You should have received a copy of the GNU - * General Public License, Version 3 along with this program; - * if not, write to the Free Software Foundation, Inc., 51 - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * 2. For the Magnolia Network Agreement (MNA), this file - * and the accompanying materials are made available under the - * terms of the MNA which accompanies this distribution, and - * is available at http://www.magnolia-cms.com/mna.html - * - * Any modifications to this file must keep this entire header - * intact. - * - */ -package info.magnolia.ui.api; - -/** - * Constants used UI Model layer and higher. - */ -public interface ModelConstants { - - /** - * Defines what value is used to indicate it is the name of {@link javax.jcr.Item} - not a property of a {@link javax.jcr.Node}. - */ - public static final String JCR_NAME = "jcrName"; -} diff --git a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/action/AbstractActionExecutor.java b/magnolia-ui-api/src/main/java/info/magnolia/ui/api/action/AbstractActionExecutor.java index 9f80c35..8e23c03 100644 --- a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/action/AbstractActionExecutor.java +++ b/magnolia-ui-api/src/main/java/info/magnolia/ui/api/action/AbstractActionExecutor.java @@ -41,13 +41,14 @@ import info.magnolia.ui.api.availability.AvailabilityDefinition; import info.magnolia.ui.api.availability.AvailabilityRule; import javax.inject.Inject; -import javax.jcr.Item; import javax.jcr.Node; import javax.jcr.RepositoryException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.vaadin.data.Item; + /** * Abstract base implementation of {@link ActionExecutor}. Creates the {@link Action} from the implementation class * using a {@link ComponentProvider} and binds the ActionDefinition to the Action. Subclasses need only implement {@link #getActionDefinition(String)}. @@ -149,29 +150,31 @@ public abstract class AbstractActionExecutor implements ActionExecutor { private boolean isAvailableForItem(AvailabilityDefinition availability, Item item) { - if (item == null) { - return availability.isRoot(); - } - - if (!item.isNode()) { - return availability.isProperties(); - } + //TODO JCRFREE - resolve this node/property logic +// if (item == null) { +// return availability.isRoot(); +// } +// +// if (!item.isNode()) { +// return availability.isProperties(); +// } // Must have _any_ of the node types if any are specified, otherwise its available by default - if (availability.getNodeTypes().isEmpty()) { - return availability.isNodes(); - } - - for (String nodeType : availability.getNodeTypes()) { - try { - if (NodeUtil.isNodeType((Node) item, nodeType)) { - return true; - } - } catch (RepositoryException e) { - log.error("Could not determine node type of node " + NodeUtil.getNodePathIfPossible((Node) item)); - } - } - - return false; +// if (availability.getNodeTypes().isEmpty()) { +// return availability.isNodes(); +// } +// +// for (String nodeType : availability.getNodeTypes()) { +// try { +// if (NodeUtil.isNodeType(item, nodeType)) { +// return true; +// } +// } catch (RepositoryException e) { +// log.error("Could not determine node type of node " + NodeUtil.getNodePathIfPossible((Node) item)); +// } +// } +// +// return false; + return true; } } diff --git a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/action/ActionExecutor.java b/magnolia-ui-api/src/main/java/info/magnolia/ui/api/action/ActionExecutor.java index 1ee6fdd..d4b5cff 100644 --- a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/action/ActionExecutor.java +++ b/magnolia-ui-api/src/main/java/info/magnolia/ui/api/action/ActionExecutor.java @@ -33,7 +33,8 @@ */ package info.magnolia.ui.api.action; -import javax.jcr.Item; + +import com.vaadin.data.Item; /** * Responsible for executing actions, doing lookups of action definitions based on action names and evaluating if an diff --git a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/AbstractAvailabilityRule.java b/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/AbstractAvailabilityRule.java index 0d179d5..4f9f2f3 100644 --- a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/AbstractAvailabilityRule.java +++ b/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/AbstractAvailabilityRule.java @@ -33,7 +33,8 @@ */ package info.magnolia.ui.api.availability; -import javax.jcr.Item; + +import com.vaadin.data.Item; /** * Abstract rule class. diff --git a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/AvailabilityRule.java b/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/AvailabilityRule.java index ce85e8c..4a17740 100644 --- a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/AvailabilityRule.java +++ b/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/AvailabilityRule.java @@ -33,7 +33,7 @@ */ package info.magnolia.ui.api.availability; -import javax.jcr.Item; +import com.vaadin.data.Item; /** * Defines the rule for additional availability restrictions. diff --git a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/HasVersionsRule.java b/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/HasVersionsRule.java index 9bd422e..815092d 100644 --- a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/HasVersionsRule.java +++ b/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/HasVersionsRule.java @@ -34,9 +34,9 @@ package info.magnolia.ui.api.availability; import info.magnolia.cms.core.version.VersionManager; +import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter; import javax.inject.Inject; -import javax.jcr.Item; import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.UnsupportedRepositoryOperationException; @@ -45,6 +45,8 @@ import javax.jcr.version.VersionHistory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.vaadin.data.Item; + /** * Checks if versioning is enabled for an item and whether it has versions. */ @@ -60,8 +62,14 @@ public class HasVersionsRule extends AbstractAvailabilityRule { @Override protected boolean isAvailableForItem(Item item) { - if (item != null && item.isNode()) { - Node node = (Node) item; + if (!(item instanceof JcrItemAdapter)) { + return false; + } + + JcrItemAdapter jcrItemAdapter = (JcrItemAdapter)item; + javax.jcr.Item jcrItem = jcrItemAdapter.getJcrItem(); + if (jcrItem != null && jcrItem.isNode()) { + Node node = (Node) jcrItem; try { VersionHistory versionHistory = versionManager.getVersionHistory(node); diff --git a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/IsDeletedRule.java b/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/IsDeletedRule.java index 8076879..fbdece9 100644 --- a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/IsDeletedRule.java +++ b/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/IsDeletedRule.java @@ -35,14 +35,16 @@ package info.magnolia.ui.api.availability; import info.magnolia.jcr.util.NodeTypes; import info.magnolia.jcr.util.NodeUtil; +import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter; -import javax.jcr.Item; import javax.jcr.Node; import javax.jcr.RepositoryException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.vaadin.data.Item; + /** * This rule returns true if the item is node and has the mgnl:deleted mixin type. */ @@ -52,8 +54,14 @@ public class IsDeletedRule extends AbstractAvailabilityRule { @Override protected boolean isAvailableForItem(Item item) { - if (item != null && item.isNode()) { - Node node = (Node) item; + if (!(item instanceof JcrItemAdapter)) { + return false; + } + + JcrItemAdapter jcrItemAdapter = (JcrItemAdapter)item; + javax.jcr.Item jcrItem = jcrItemAdapter.getJcrItem(); + if (jcrItem != null && jcrItem.isNode()) { + Node node = (Node) jcrItem; try { return NodeUtil.hasMixin(node, NodeTypes.Deleted.NAME); } catch (RepositoryException e) { diff --git a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/IsNotDeletedRule.java b/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/IsNotDeletedRule.java index 4f7686c..ac1e92f 100644 --- a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/IsNotDeletedRule.java +++ b/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/IsNotDeletedRule.java @@ -35,14 +35,16 @@ package info.magnolia.ui.api.availability; import info.magnolia.jcr.util.NodeTypes; import info.magnolia.jcr.util.NodeUtil; +import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter; -import javax.jcr.Item; import javax.jcr.Node; import javax.jcr.RepositoryException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.vaadin.data.Item; + /** * This rule returns true if the item is not a node, or if it is a node and has NOT the mgnl:deleted mixin type. */ @@ -52,8 +54,14 @@ public class IsNotDeletedRule extends AbstractAvailabilityRule { @Override public boolean isAvailableForItem(Item item) { - if (item != null && item.isNode()) { - Node node = (Node) item; + if (!(item instanceof JcrItemAdapter)) { + return false; + } + + JcrItemAdapter jcrItemAdapter = (JcrItemAdapter)item; + javax.jcr.Item jcrItem = jcrItemAdapter.getJcrItem(); + if (jcrItem != null && jcrItem.isNode()) { + Node node = (Node) jcrItem; try { return !NodeUtil.hasMixin(node, NodeTypes.Deleted.NAME); } catch (RepositoryException e) { diff --git a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/IsNotVersionedRule.java b/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/IsNotVersionedRule.java index 7b132bc..c696060 100644 --- a/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/IsNotVersionedRule.java +++ b/magnolia-ui-api/src/main/java/info/magnolia/ui/api/availability/IsNotVersionedRule.java @@ -35,8 +35,8 @@ package info.magnolia.ui.api.availability; import info.magnolia.jcr.util.NodeUtil; import info.magnolia.repository.RepositoryConstants; +import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter; -import javax.jcr.Item; import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.version.Version; @@ -44,6 +44,8 @@ import javax.jcr.version.Version; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.vaadin.data.Item; + /** * Availability rule for non-versioned items. */ @@ -53,8 +55,15 @@ public class IsNotVersionedRule extends AbstractAvailabilityRule { @Override protected boolean isAvailableForItem(Item item) { - if (item != null && item.isNode()) { - Node node = (Node) item; + if (!(item instanceof JcrItemAdapter)) { + return false; + } + + JcrItemAdapter jcrItemAdapter = (JcrItemAdapter)item; + javax.jcr.Item jcrItem = jcrItemAdapter.getJcrItem(); + + if (jcrItem != null && jcrItem.isNode()) { + Node node = (Node) jcrItem; if (node instanceof Version) { return false; diff --git a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/availability/IsNotVersionedDetailLocationRule.java b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/availability/IsNotVersionedDetailLocationRule.java index 78dd336..2368f41 100644 --- a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/availability/IsNotVersionedDetailLocationRule.java +++ b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/availability/IsNotVersionedDetailLocationRule.java @@ -38,7 +38,8 @@ import info.magnolia.ui.api.availability.AbstractAvailabilityRule; import info.magnolia.ui.contentapp.detail.DetailLocation; import javax.inject.Inject; -import javax.jcr.Item; + +import com.vaadin.data.Item; /** * Availability rule that checks if the current {@link DetailLocation} is versioned or not. diff --git a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserPresenter.java b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserPresenter.java index 6c9212f..b82de85 100644 --- a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserPresenter.java +++ b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserPresenter.java @@ -36,32 +36,21 @@ package info.magnolia.ui.contentapp.browser; import info.magnolia.event.EventBus; import info.magnolia.objectfactory.ComponentProvider; import info.magnolia.ui.actionbar.ActionbarPresenter; -import info.magnolia.ui.actionbar.definition.ActionbarDefinition; -import info.magnolia.ui.api.action.ActionDefinition; -import info.magnolia.ui.api.action.ActionExecutionException; import info.magnolia.ui.api.action.ActionExecutor; -import info.magnolia.ui.api.app.AppContext; import info.magnolia.ui.api.app.SubAppContext; import info.magnolia.ui.api.app.SubAppEventBus; import info.magnolia.ui.api.event.AdmincentralEventBus; -import info.magnolia.ui.api.event.ContentChangedEvent; import info.magnolia.ui.api.message.Message; import info.magnolia.ui.api.message.MessageType; import info.magnolia.ui.imageprovider.ImageProvider; import info.magnolia.ui.imageprovider.definition.ImageProviderDefinition; -import info.magnolia.ui.vaadin.actionbar.ActionbarView; import info.magnolia.ui.vaadin.integration.jcr.AbstractJcrNodeAdapter; import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter; import info.magnolia.ui.vaadin.integration.jcr.JcrItemUtil; import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter; import info.magnolia.ui.vaadin.integration.jcr.JcrPropertyAdapter; import info.magnolia.ui.workbench.WorkbenchPresenter; -import info.magnolia.ui.workbench.WorkbenchView; -import info.magnolia.ui.workbench.event.ItemDoubleClickedEvent; import info.magnolia.ui.workbench.event.ItemEditedEvent; -import info.magnolia.ui.workbench.event.ItemShortcutKeyEvent; -import info.magnolia.ui.workbench.event.SearchEvent; -import info.magnolia.ui.workbench.event.SelectionChangedEvent; import java.util.ArrayList; import java.util.List; @@ -78,57 +67,24 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.vaadin.data.Item; -import com.vaadin.event.ShortcutAction; -import com.vaadin.server.Resource; - /** - * The browser is a core component of AdminCentral. It represents the main hub through which users can interact with - * JCR data. It is compounded by three main sub-components: - *
    - *
  • a configurable data grid. - *
  • a configurable function toolbar on top of the data grid, providing operations such as switching from tree to list view or thumbnail view or performing searches on data. - *
  • a configurable action bar on the right hand side, showing the available operations for the given workspace and the selected item. - *
- *

- * Its main configuration point is the {@link info.magnolia.ui.workbench.definition.WorkbenchDefinition} through which one defines the JCR workspace to connect to, the columns/properties to display, the available actions and so on. + * Created with IntelliJ IDEA. + * User: sasha + * Date: 31/01/14 + * Time: 16:35 + * To change this template use File | Settings | File Templates. */ -public class BrowserPresenter implements ActionbarPresenter.Listener, BrowserView.Listener { - - private static final Logger log = LoggerFactory.getLogger(BrowserPresenter.class); - - private WorkbenchPresenter workbenchPresenter; - - private final ActionExecutor actionExecutor; - - private BrowserSubAppDescriptor subAppDescriptor; - - private final BrowserView view; +public class BrowserPresenter extends BrowserPresenterBase { - private final EventBus admincentralEventBus; - - private final EventBus subAppEventBus; - - private final ActionbarPresenter actionbarPresenter; + private Logger log = LoggerFactory.getLogger(getClass()); private final ImageProvider imageProvider; - private final AppContext appContext; - @Inject - public BrowserPresenter(final ActionExecutor actionExecutor, final SubAppContext subAppContext, final BrowserView view, @Named(AdmincentralEventBus.NAME) final EventBus admincentralEventBus, - final @Named(SubAppEventBus.NAME) EventBus subAppEventBus, - final ActionbarPresenter actionbarPresenter, final ComponentProvider componentProvider, WorkbenchPresenter workbenchPresenter) { - this.workbenchPresenter = workbenchPresenter; - this.actionExecutor = actionExecutor; - this.view = view; - this.admincentralEventBus = admincentralEventBus; - this.subAppEventBus = subAppEventBus; - this.actionbarPresenter = actionbarPresenter; - this.appContext = subAppContext.getAppContext(); - this.subAppDescriptor = (BrowserSubAppDescriptor) subAppContext.getSubAppDescriptor(); - - ImageProviderDefinition imageProviderDefinition = subAppDescriptor.getImageProvider(); + public BrowserPresenter(ActionExecutor actionExecutor, SubAppContext subAppContext, BrowserView view, @Named(AdmincentralEventBus.NAME) EventBus admincentralEventBus, @Named(SubAppEventBus.NAME) EventBus subAppEventBus, ActionbarPresenter actionbarPresenter, ComponentProvider componentProvider, WorkbenchPresenter workbenchPresenter) { + super(actionExecutor, subAppContext, view, admincentralEventBus, subAppEventBus, actionbarPresenter, workbenchPresenter); + ImageProviderDefinition imageProviderDefinition = ((BrowserSubAppDescriptor) subAppContext.getSubAppDescriptor()).getImageProvider(); if (imageProviderDefinition == null) { this.imageProvider = null; } else { @@ -136,151 +92,8 @@ public class BrowserPresenter implements ActionbarPresenter.Listener, BrowserVie } } - public BrowserView start() { - actionbarPresenter.setListener(this); - - WorkbenchView workbenchView = workbenchPresenter.start(subAppDescriptor.getWorkbench(), subAppDescriptor.getImageProvider(), subAppEventBus); - ActionbarView actionbar = actionbarPresenter.start(subAppDescriptor.getActionbar()); - - view.setWorkbenchView(workbenchView); - view.setActionbarView(actionbar); - view.setListener(this); - - bindHandlers(); - return view; - } - - private void bindHandlers() { - admincentralEventBus.addHandler(ContentChangedEvent.class, new ContentChangedEvent.Handler() { - - @Override - public void onContentChanged(ContentChangedEvent event) { - if (event.getWorkspace().equals(getWorkspace())) { - - workbenchPresenter.refresh(); - - workbenchPresenter.select(getSelectedItemIds()); - - if (event.isItemContentChanged()) { - workbenchPresenter.expand(event.getItemId()); - } - - // use just the first selected item to show the preview image - String itemId = getSelectedItemIds().get(0); - try { - if (JcrItemUtil.itemExists(getWorkspace(), itemId)) { - refreshActionbarPreviewImage(itemId, event.getWorkspace()); - } - } catch (RepositoryException e) { - log.warn("Unable to get node or property [{}] for preview image", itemId, e); - } - } - } - }); - - subAppEventBus.addHandler(SelectionChangedEvent.class, new SelectionChangedEvent.Handler() { - - @Override - public void onSelectionChanged(SelectionChangedEvent event) { - // if exactly one node is selected, use it for preview - refreshActionbarPreviewImage(event.getFirstItemId(), event.getWorkspace()); - } - }); - - subAppEventBus.addHandler(ItemDoubleClickedEvent.class, new ItemDoubleClickedEvent.Handler() { - - @Override - public void onItemDoubleClicked(ItemDoubleClickedEvent event) { - executeDefaultAction(); - } - }); - - subAppEventBus.addHandler(SearchEvent.class, new SearchEvent.Handler() { - - @Override - public void onSearch(SearchEvent event) { - workbenchPresenter.doSearch(event.getSearchExpression()); - } - }); - - subAppEventBus.addHandler(ItemEditedEvent.class, new ItemEditedEvent.Handler() { - - @Override - public void onItemEdited(ItemEditedEvent event) { - editItem(event); - } - }); - - subAppEventBus.addHandler(ItemShortcutKeyEvent.class, new ItemShortcutKeyEvent.Handler() { - - @Override - public void onItemShortcutKeyEvent(ItemShortcutKeyEvent event) { - int keyCode = event.getKeyCode(); - switch (keyCode) { - case ShortcutAction.KeyCode.ENTER: - executeDefaultAction(); - break; - case ShortcutAction.KeyCode.DELETE: - executeDeleteAction(); - break; - } - - } - }); - } - - public List getSelectedItemIds() { - return workbenchPresenter.getSelectedIds(); - } - - /** - * @return The configured default view Type.
- * If non define, return the first Content Definition as default. - */ - public String getDefaultViewType() { - return workbenchPresenter.getDefaultViewType(); - } - - public boolean hasViewType(String viewType) { - return workbenchPresenter.hasViewType(viewType); - } - - public BrowserView getView() { - return view; - } - - public ActionbarPresenter getActionbarPresenter() { - return actionbarPresenter; - } - - public String getWorkspace() { - return workbenchPresenter.getWorkspace(); - } - - /** - * Synchronizes the underlying view to reflect the status extracted from the Location token, i.e. selected itemId, - * view type and optional query (in case of a search view). - */ - public void resync(final List itemIds, final String viewType, final String query) { - workbenchPresenter.resynch(itemIds, viewType, query); - } - - private void refreshActionbarPreviewImage(final String itemId, final String workspace) { - if (StringUtils.isBlank(itemId)) { - actionbarPresenter.setPreview(null); - } else { - if (imageProvider != null) { - Object previewResource = imageProvider.getThumbnailResourceById(workspace, itemId, ImageProvider.PORTRAIT_GENERATOR); - if (previewResource instanceof Resource) { - actionbarPresenter.setPreview((Resource) previewResource); - } else { - actionbarPresenter.setPreview(null); - } - } - } - } - - private void editItem(ItemEditedEvent event) { + @Override + protected void editItem(ItemEditedEvent event) { Item item = event.getItem(); // we support only JCR item adapters @@ -318,7 +131,7 @@ public class BrowserPresenter implements ActionbarPresenter.Listener, BrowserVie // update workbench selection in case the property changed name List ids = new ArrayList(); ids.add(JcrItemUtil.getItemId(propertyAdapter.getJcrItem())); - workbenchPresenter.select(ids); + getWorkbenchPresenter().select(ids); } catch (RepositoryException e) { log.error("Could not save changes to property", e); @@ -327,94 +140,49 @@ public class BrowserPresenter implements ActionbarPresenter.Listener, BrowserVie } @Override - public void onActionbarItemClicked(String itemName) { - executeAction(itemName); - } - - @Override - public void onActionBarSelection(String actionName) { - executeAction(actionName); - } - - @Override - public String getLabel(String itemName) { - ActionDefinition actionDefinition = actionExecutor.getActionDefinition(itemName); - return actionDefinition != null ? actionDefinition.getLabel() : null; - } - - @Override - public String getIcon(String itemName) { - ActionDefinition actionDefinition = actionExecutor.getActionDefinition(itemName); - return actionDefinition != null ? actionDefinition.getIcon() : null; - } - - /** - * Executes the default action, as configured in the {@link info.magnolia.ui.actionbar.definition.ActionbarDefinition}. - */ - private void executeDefaultAction() { - ActionbarDefinition actionbarDefinition = subAppDescriptor.getActionbar(); - if (actionbarDefinition == null) { - return; - } - String defaultAction = actionbarDefinition.getDefaultAction(); - if (StringUtils.isNotEmpty(defaultAction)) { - executeAction(defaultAction); + public List getSelectedItems() { + List items = new ArrayList(getSelectedItemIds().size()); + List jcrItems = new ArrayList(getSelectedItemIds().size()); + for (Object itemId : getSelectedItemIds()) { + try { + javax.jcr.Item item = JcrItemUtil.getJcrItem(getWorkspace(), String.valueOf(itemId)); + jcrItems.add(item); + JcrItemAdapter adapter = item.isNode() ? new JcrNodeAdapter((Node) item) : new JcrPropertyAdapter((Property) item); + items.add(adapter); + } catch (PathNotFoundException p) { + Message error = new Message(MessageType.ERROR, "Could not get item ", "Following Item not found :" + getSelectedItemIds().get(0)); + getAppContext().sendLocalMessage(error); + } catch (RepositoryException e) { + Message error = new Message(MessageType.ERROR, "Could not get item: " + getSelectedItemIds().get(0), e.getMessage()); + //log.error("An error occurred while executing action [{}]", actionName, e); + getAppContext().sendLocalMessage(error); + } } + return items; } - /** - * Executes the default delete action, as configured in the {@link info.magnolia.ui.actionbar.definition.ActionbarDefinition}. - */ - private void executeDeleteAction() { - ActionbarDefinition actionbarDefinition = subAppDescriptor.getActionbar(); - if (actionbarDefinition == null) { - return; - } - String deleteAction = actionbarDefinition.getDeleteAction(); - if (StringUtils.isNotEmpty(deleteAction)) { - executeAction(deleteAction); + @Override + protected boolean verifyItemExists(Object itemId) { + try { + return JcrItemUtil.itemExists(getWorkspace(), String.valueOf(itemId)); + } catch (RepositoryException e) { + log.warn("Unable to get node or property [{}] for preview image", itemId, e); + return false; } } - private void executeAction(String actionName) { - try { - if (getSelectedItemIds().size() == 1) { - // This is done this way, because most actions do not support multiple items, and expect just one Item - // in the constructor. So if we passed List containing this one Item to the ActionExecutor, it'd - // fail, because the ComponentProvider wouldn't find suitable constructor for the Action. - // Changing this would require to rewrite all the actions to accept the List in the constructor... - javax.jcr.Item item = JcrItemUtil.getJcrItem(getWorkspace(), getSelectedItemIds().get(0)); - String workbenchRootId = JcrItemUtil.getItemId(getWorkspace(), subAppDescriptor.getWorkbench().getPath()); - boolean isWorkbenchRoot = JcrItemUtil.getItemId(item).equals(workbenchRootId); - // if the item is workbench root (i.e. no real item is selected), we have to pass null to the isAvailable method - if (actionExecutor.isAvailable(actionName, isWorkbenchRoot ? null : item)) { - actionExecutor.execute(actionName, item.isNode() ? new JcrNodeAdapter((Node) item) : new JcrPropertyAdapter((Property) item)); - } - } else { - List items = new ArrayList(getSelectedItemIds().size()); - List jcrItems = new ArrayList(getSelectedItemIds().size()); - for (String itemId : getSelectedItemIds()) { - javax.jcr.Item item = JcrItemUtil.getJcrItem(getWorkspace(), itemId); - jcrItems.add(item); - JcrItemAdapter adapter = item.isNode() ? new JcrNodeAdapter((Node) item) : new JcrPropertyAdapter((Property) item); - items.add(adapter); - } - if (actionExecutor.isAvailable(actionName, jcrItems.toArray(new javax.jcr.Item[] {}))) { - actionExecutor.execute(actionName, items); - } + @Override + protected Object getPreviewImageForId(Object itemId) { + if (StringUtils.isBlank(String.valueOf(itemId))) { + return null; + } else { + if (imageProvider != null) { + return imageProvider.getThumbnailResourceById(getWorkbenchPresenter().getWorkspace(), String.valueOf(itemId), ImageProvider.PORTRAIT_GENERATOR); } - } catch (PathNotFoundException p) { - Message error = new Message(MessageType.ERROR, "Could not get item ", "Following Item not found :" + getSelectedItemIds().get(0)); - appContext.sendLocalMessage(error); - } catch (RepositoryException e) { - Message error = new Message(MessageType.ERROR, "Could not get item: " + getSelectedItemIds().get(0), e.getMessage()); - log.error("An error occurred while executing action [{}]", actionName, e); - appContext.sendLocalMessage(error); - } catch (ActionExecutionException e) { - Message error = new Message(MessageType.ERROR, "An error occurred while executing an action.", e.getMessage()); - log.error("An error occurred while executing action [{}]", actionName, e); - appContext.sendLocalMessage(error); } + return null; } } + + diff --git a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserPresenterBase.java b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserPresenterBase.java new file mode 100644 index 0000000..e594d93 --- /dev/null +++ b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserPresenterBase.java @@ -0,0 +1,332 @@ +/** + * This file Copyright (c) 2012-2013 Magnolia International + * Ltd. (http://www.magnolia-cms.com). All rights reserved. + * + * + * This file is dual-licensed under both the Magnolia + * Network Agreement and the GNU General Public License. + * You may elect to use one or the other of these licenses. + * + * This file is distributed in the hope that it will be + * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. + * Redistribution, except as permitted by whichever of the GPL + * or MNA you select, is prohibited. + * + * 1. For the GPL license (GPL), you can redistribute and/or + * modify this file under the terms of the GNU General + * Public License, Version 3, as published by the Free Software + * Foundation. You should have received a copy of the GNU + * General Public License, Version 3 along with this program; + * if not, write to the Free Software Foundation, Inc., 51 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 2. For the Magnolia Network Agreement (MNA), this file + * and the accompanying materials are made available under the + * terms of the MNA which accompanies this distribution, and + * is available at http://www.magnolia-cms.com/mna.html + * + * Any modifications to this file must keep this entire header + * intact. + * + */ +package info.magnolia.ui.contentapp.browser; + +import info.magnolia.event.EventBus; +import info.magnolia.ui.actionbar.ActionbarPresenter; +import info.magnolia.ui.actionbar.ActionbarView; +import info.magnolia.ui.actionbar.definition.ActionbarDefinition; +import info.magnolia.ui.api.action.ActionExecutionException; +import info.magnolia.ui.api.action.ActionExecutor; +import info.magnolia.ui.api.app.AppContext; +import info.magnolia.ui.api.app.SubAppContext; +import info.magnolia.ui.api.app.SubAppEventBus; +import info.magnolia.ui.api.event.AdmincentralEventBus; +import info.magnolia.ui.api.event.ContentChangedEvent; +import info.magnolia.ui.api.message.Message; +import info.magnolia.ui.api.message.MessageType; +import info.magnolia.ui.vaadin.integration.NullItem; +import info.magnolia.ui.workbench.WorkbenchPresenterBase; +import info.magnolia.ui.workbench.WorkbenchView; +import info.magnolia.ui.workbench.event.ItemDoubleClickedEvent; +import info.magnolia.ui.workbench.event.ItemEditedEvent; +import info.magnolia.ui.workbench.event.ItemShortcutKeyEvent; +import info.magnolia.ui.workbench.event.SearchEvent; +import info.magnolia.ui.workbench.event.SelectionChangedEvent; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Named; + +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.vaadin.data.Item; +import com.vaadin.event.ShortcutAction; +import com.vaadin.server.Resource; + + +/** + * The browser is a core component of AdminCentral. It represents the main hub through which users can interact with + * JCR data. It is compounded by three main sub-components: + *

    + *
  • a configurable data grid. + *
  • a configurable function toolbar on top of the data grid, providing operations such as switching from tree to list view or thumbnail view or performing searches on data. + *
  • a configurable action bar on the right hand side, showing the available operations for the given workspace and the selected item. + *
+ *

+ * Its main configuration point is the {@link info.magnolia.ui.workbench.definition.WorkbenchDefinition} through which one defines the JCR workspace to connect to, the columns/properties to display, the available actions and so on. + * TODO JCRFREE - consider generic id type here. + */ +public abstract class BrowserPresenterBase implements ActionbarPresenter.Listener, BrowserView.Listener { + + private static final Logger log = LoggerFactory.getLogger(BrowserPresenter.class); + + private WorkbenchPresenterBase workbenchPresenter; + + private final ActionExecutor actionExecutor; + + private BrowserSubAppDescriptor subAppDescriptor; + + private final BrowserView view; + + private final EventBus admincentralEventBus; + + private final EventBus subAppEventBus; + + private final ActionbarPresenter actionbarPresenter; + + private final AppContext appContext; + + public BrowserPresenterBase(final ActionExecutor actionExecutor, final SubAppContext subAppContext, final BrowserView view, @Named(AdmincentralEventBus.NAME) final EventBus admincentralEventBus, + final @Named(SubAppEventBus.NAME) EventBus subAppEventBus, + final ActionbarPresenter actionbarPresenter, WorkbenchPresenterBase workbenchPresenter) { + this.workbenchPresenter = workbenchPresenter; + this.actionExecutor = actionExecutor; + this.view = view; + this.admincentralEventBus = admincentralEventBus; + this.subAppEventBus = subAppEventBus; + this.actionbarPresenter = actionbarPresenter; + this.appContext = subAppContext.getAppContext(); + this.subAppDescriptor = (BrowserSubAppDescriptor) subAppContext.getSubAppDescriptor(); + } + + + protected abstract void editItem(ItemEditedEvent event); + + public BrowserView start() { + actionbarPresenter.setListener(this); + + WorkbenchView workbenchView = workbenchPresenter.start(subAppDescriptor.getWorkbench(), subAppDescriptor.getImageProvider(), subAppEventBus); + ActionbarView actionbar = actionbarPresenter.start(subAppDescriptor.getActionbar(), subAppDescriptor.getActions()); + + view.setWorkbenchView(workbenchView); + view.setActionbarView(actionbar); + view.setListener(this); + + bindHandlers(); + return view; + } + + private void bindHandlers() { + admincentralEventBus.addHandler(ContentChangedEvent.class, new ContentChangedEvent.Handler() { + + @Override + public void onContentChanged(ContentChangedEvent event) { + if (event.getWorkspace().equals(getWorkspace())) { + + workbenchPresenter.refresh(); + + workbenchPresenter.select(getSelectedItemIds()); + + if (event.isItemContentChanged()) { + workbenchPresenter.expand(event.getItemId()); + } + + // use just the first selected item to show the preview image + Object itemId = getSelectedItemIds().get(0); + if (verifyItemExists(itemId)) { + refreshActionbarPreviewImage(itemId); + } + + } + } + }); + + subAppEventBus.addHandler(SelectionChangedEvent.class, new SelectionChangedEvent.Handler() { + + @Override + public void onSelectionChanged(SelectionChangedEvent event) { + // if exactly one node is selected, use it for preview + refreshActionbarPreviewImage(event.getFirstItemId()); + } + }); + + subAppEventBus.addHandler(ItemDoubleClickedEvent.class, new ItemDoubleClickedEvent.Handler() { + + @Override + public void onItemDoubleClicked(ItemDoubleClickedEvent event) { + executeDefaultAction(); + } + }); + + subAppEventBus.addHandler(SearchEvent.class, new SearchEvent.Handler() { + + @Override + public void onSearch(SearchEvent event) { + workbenchPresenter.doSearch(event.getSearchExpression()); + } + }); + + subAppEventBus.addHandler(ItemEditedEvent.class, new ItemEditedEvent.Handler() { + + @Override + public void onItemEdited(ItemEditedEvent event) { + editItem(event); + } + }); + + subAppEventBus.addHandler(ItemShortcutKeyEvent.class, new ItemShortcutKeyEvent.Handler() { + + @Override + public void onItemShortcutKeyEvent(ItemShortcutKeyEvent event) { + int keyCode = event.getKeyCode(); + switch (keyCode) { + case ShortcutAction.KeyCode.ENTER: + executeDefaultAction(); + break; + case ShortcutAction.KeyCode.DELETE: + executeDeleteAction(); + break; + } + + } + }); + } + + private void refreshActionbarPreviewImage(Object itemId) { + Object previewResource = getPreviewImageForId(itemId); + if (previewResource instanceof Resource) { + getActionbarPresenter().setPreview((Resource) previewResource); + } else { + getActionbarPresenter().setPreview(null); + } + } + + protected boolean verifyItemExists(Object itemId) { + return getWorkbenchPresenter().getItemFor(itemId) != null; + } + + public List getSelectedItemIds() { + return workbenchPresenter.getSelectedIds(); + } + + /** + * @return The configured default view Type.
+ * If non define, return the first Content Definition as default. + */ + public String getDefaultViewType() { + return workbenchPresenter.getDefaultViewType(); + } + + public boolean hasViewType(String viewType) { + return workbenchPresenter.hasViewType(viewType); + } + + public BrowserView getView() { + return view; + } + + public ActionbarPresenter getActionbarPresenter() { + return actionbarPresenter; + } + + public String getWorkspace() { + return workbenchPresenter.getWorkspace(); + } + + /** + * Synchronizes the underlying view to reflect the status extracted from the Location token, i.e. selected itemId, + * view type and optional query (in case of a search view). + * TODO JCRFREE - consider generic id type here + */ + public void resync(final List itemIds, final String viewType, final String query) { + workbenchPresenter.resynch(itemIds, viewType, query); + } + + protected abstract Object getPreviewImageForId(final Object itemId); + + @Override + public void onActionbarItemClicked(String itemName) { + executeAction(itemName); + } + + + + @Override + public void onActionBarSelection(String actionName) { + executeAction(actionName); + } + + public WorkbenchPresenterBase getWorkbenchPresenter() { + return workbenchPresenter; + } + + /** + * Executes the default action, as configured in the {@link info.magnolia.ui.actionbar.definition.ActionbarDefinition}. + */ + private void executeDefaultAction() { + ActionbarDefinition actionbarDefinition = subAppDescriptor.getActionbar(); + if (actionbarDefinition == null) { + return; + } + String defaultAction = actionbarDefinition.getDefaultAction(); + if (StringUtils.isNotEmpty(defaultAction)) { + executeAction(defaultAction); + } + } + + /** + * Executes the default delete action, as configured in the {@link info.magnolia.ui.actionbar.definition.ActionbarDefinition}. + */ + private void executeDeleteAction() { + ActionbarDefinition actionbarDefinition = subAppDescriptor.getActionbar(); + if (actionbarDefinition == null) { + return; + } + String deleteAction = actionbarDefinition.getDeleteAction(); + if (StringUtils.isNotEmpty(deleteAction)) { + executeAction(deleteAction); + } + } + + private void executeAction(String actionName) { + try { + List items = getSelectedItems(); + if (actionExecutor.isAvailable(actionName, items.toArray(new Item[items.size()]))) { + actionExecutor.execute(actionName, items, items.isEmpty() ? new NullItem() : items.get(0)); + } + } catch (ActionExecutionException e) { + Message error = new Message(MessageType.ERROR, "An error occurred while executing an action.", e.getMessage()); + log.error("An error occurred while executing action [{}]", actionName, e); + appContext.sendLocalMessage(error); + } + } + + protected AppContext getAppContext() { + return appContext; + } + + public List getSelectedItems() { + WorkbenchPresenterBase workbenchPresenter = getWorkbenchPresenter(); + List selectedIds = workbenchPresenter.getSelectedIds(); + List result = new ArrayList(selectedIds.size()); + for (Object id : selectedIds) { + result.add(workbenchPresenter.getItemFor(id)); + } + return result; + } +} diff --git a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserSubApp.java b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserSubApp.java index eb1ccb7..503cc81 100644 --- a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserSubApp.java +++ b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserSubApp.java @@ -33,515 +33,149 @@ */ package info.magnolia.ui.contentapp.browser; -import info.magnolia.context.MgnlContext; import info.magnolia.event.EventBus; import info.magnolia.jcr.util.NodeUtil; import info.magnolia.jcr.util.SessionUtil; import info.magnolia.objectfactory.ComponentProvider; -import info.magnolia.ui.actionbar.ActionbarPresenter; -import info.magnolia.ui.actionbar.definition.ActionbarDefinition; -import info.magnolia.ui.actionbar.definition.ActionbarGroupDefinition; -import info.magnolia.ui.actionbar.definition.ActionbarItemDefinition; -import info.magnolia.ui.actionbar.definition.ActionbarSectionDefinition; -import info.magnolia.ui.api.action.ActionDefinition; import info.magnolia.ui.api.action.ActionExecutor; import info.magnolia.ui.api.app.SubAppContext; import info.magnolia.ui.api.app.SubAppEventBus; import info.magnolia.ui.api.availability.AvailabilityDefinition; -import info.magnolia.ui.api.availability.AvailabilityRule; -import info.magnolia.ui.api.location.Location; import info.magnolia.ui.contentapp.ContentSubAppView; -import info.magnolia.ui.framework.app.BaseSubApp; -import info.magnolia.ui.vaadin.actionbar.ActionPopup; +import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter; import info.magnolia.ui.vaadin.integration.jcr.JcrItemUtil; +import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter; +import info.magnolia.ui.vaadin.integration.jcr.JcrPropertyAdapter; import info.magnolia.ui.workbench.definition.WorkbenchDefinition; -import info.magnolia.ui.workbench.event.ItemRightClickedEvent; -import info.magnolia.ui.workbench.event.SearchEvent; -import info.magnolia.ui.workbench.event.SelectionChangedEvent; -import info.magnolia.ui.workbench.event.ViewTypeChangedEvent; -import info.magnolia.ui.workbench.search.SearchPresenterDefinition; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; import javax.inject.Named; -import javax.jcr.Item; import javax.jcr.Node; +import javax.jcr.Property; import javax.jcr.RepositoryException; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.vaadin.peter.contextmenu.ContextMenu; -import com.vaadin.server.ExternalResource; +import com.vaadin.data.Item; /** - * Base implementation of a content subApp. A content subApp displays a collection of data represented inside a {@link info.magnolia.ui.workbench.ContentView} created by the {@link info.magnolia.ui.workbench.WorkbenchPresenter}. - * - *
- *  

- * This class Provides sensible implementation for services shared by all content subApps. - * Out-of-the-box it will handle the following: - *

- * - *
    - *
  • location updates when switching views, selecting items or performing searches: see {@link #locationChanged(Location)} - *
  • restoring the browser app status when i.e. coming from a bookmark: see {@link #start(Location)} - *
- * In order to perform those tasks this class registers non-overridable handlers for the following events: - *
    - *
  • {@link SelectionChangedEvent} - *
  • {@link ViewTypeChangedEvent} - *
  • {@link SearchEvent} - *
- * Subclasses can augment the default behavior and perform additional tasks by overriding the following methods: - *
    - *
  • {@link #onSubAppStart()} - *
  • {@link #locationChanged(Location)} - *
  • {@link #updateActionbar(ActionbarPresenter)} - *
- *
- * - * @see BrowserPresenter - * @see info.magnolia.ui.contentapp.ContentSubAppView - * @see info.magnolia.ui.contentapp.ContentApp - * @see BrowserLocation + * Created with IntelliJ IDEA. + * User: sasha + * Date: 31/01/14 + * Time: 15:38 + * To change this template use File | Settings | File Templates. */ -public class BrowserSubApp extends BaseSubApp { +public class BrowserSubApp extends BrowserSubAppBase { - private static final Logger log = LoggerFactory.getLogger(BrowserSubApp.class); - - private final BrowserPresenter browser; - private final EventBus subAppEventBus; - private ActionExecutor actionExecutor; - private ComponentProvider componentProvider; - private String workbenchRoot; + private Logger log = LoggerFactory.getLogger(getClass()); @Inject public BrowserSubApp(ActionExecutor actionExecutor, final SubAppContext subAppContext, final ContentSubAppView view, final BrowserPresenter browser, final @Named(SubAppEventBus.NAME) EventBus subAppEventBus, final ComponentProvider componentProvider) { - super(subAppContext, view); - if (subAppContext == null || view == null || browser == null || subAppEventBus == null) { - throw new IllegalArgumentException("Constructor does not allow for null args. Found SubAppContext = " + subAppContext + ", ContentSubAppView = " + view + ", BrowserPresenter = " + browser + ", EventBus = " + subAppEventBus); - } - this.browser = browser; - this.subAppEventBus = subAppEventBus; - this.actionExecutor = actionExecutor; - this.componentProvider = componentProvider; - this.workbenchRoot = ((BrowserSubAppDescriptor) subAppContext.getSubAppDescriptor()).getWorkbench().getPath(); + super(actionExecutor, subAppContext, view, browser, subAppEventBus, componentProvider); } - /** - * Performs some routine tasks needed by all content subapps before the view is displayed. - * The tasks are: - *
    - *
  • setting the current location - *
  • setting the browser view - *
  • restoring the browser status: see {@link #restoreBrowser(BrowserLocation)} - *
  • calling {@link #onSubAppStart()} a hook-up method subclasses can override to perform additional work. - *
- */ @Override - public ContentSubAppView start(final Location location) { - BrowserLocation l = BrowserLocation.wrap(location); - super.start(l); - getView().setContentView(browser.start()); - restoreBrowser(l); - registerSubAppEventsHandlers(subAppEventBus, this); - - return getView(); - } - - /** - * Restores the browser status based on the information available in the location object. This is used e.g. when starting a subapp based on a - * bookmark. I.e. given a bookmark containing the following URI fragment - *

- * {@code - * #app:myapp:browser;/foo/bar:list - * } - *

- * this method will select the path /foo/bar in the workspace used by the app, set the view type as list and finally update the available actions. - *

- * In case of a search view the URI fragment will look similar to the following one {@code - * #app:myapp:browser;/:search:qux - * } - *

- * then this method will select the root path, set the view type as search, perform a search for "qux" in the workspace used by the app and finally update the available actions. - * - * @see BrowserSubApp#updateActionbar(ActionbarPresenter) - * @see BrowserSubApp#start(Location) - * @see Location - */ - protected void restoreBrowser(final BrowserLocation location) { - String path = ("/".equals(workbenchRoot) ? "" : workbenchRoot) + location.getNodePath(); - String viewType = location.getViewType(); - - if (!getBrowser().hasViewType(viewType)) { - if (!StringUtils.isBlank(viewType)) { - log.warn("Unknown view type [{}], returning to default view type.", viewType); - } - viewType = getBrowser().getDefaultViewType(); - location.updateViewType(viewType); - getAppContext().updateSubAppLocation(getSubAppContext(), location); - } - String query = location.getQuery(); - - BrowserSubAppDescriptor subAppDescriptor = (BrowserSubAppDescriptor) getSubAppContext().getSubAppDescriptor(); - final String workspaceName = subAppDescriptor.getWorkbench().getWorkspace(); - + protected Object ensureSelection(String urlFragmentPath, WorkbenchDefinition workbench) { + String workspaceName = workbench.getWorkspace(); String itemId = null; try { - itemId = JcrItemUtil.getItemId(SessionUtil.getNode(workspaceName, path)); + itemId = JcrItemUtil.getItemId(SessionUtil.getNode(workspaceName, urlFragmentPath)); // MGNLUI-1475: item might have not been found if path doesn't exist if (itemId == null) { - itemId = JcrItemUtil.getItemId(SessionUtil.getNode(workspaceName, workbenchRoot)); + itemId = String.valueOf(getRootItemId()); BrowserLocation newLocation = getCurrentLocation(); newLocation.updateNodePath("/"); - getAppContext().updateSubAppLocation(getSubAppContext(), newLocation); } } catch (RepositoryException e) { - log.warn("Could not retrieve item at path {} in workspace {}", path, workspaceName); + log.warn("Could not retrieve item at path {} in workspace {}", urlFragmentPath, workspaceName); } - List ids = new ArrayList(); - if (itemId != null) { - ids.add(itemId); - } - getBrowser().resync(ids, viewType, query); - updateActionbar(getBrowser().getActionbarPresenter()); + return itemId; } - /** - * Show the actionPopup for the specified item at the specified coordinates. - */ - public void showActionPopup(String absItemPath, int x, int y) { - - // If there's no actionbar configured we don't want to show an empty action popup - BrowserSubAppDescriptor subAppDescriptor = (BrowserSubAppDescriptor) getSubAppContext().getSubAppDescriptor(); - ActionbarDefinition actionbarDefinition = subAppDescriptor.getActionbar(); - if (actionbarDefinition == null) { - return; - } - - ActionPopup actionPopup = browser.getView().getActionPopup(); - - updateActionPopup(actionPopup); - actionPopup.open(x, y); + @Override + protected List getSelectedItems() { + WorkbenchDefinition workbench = getWorkbench(); + return getItemsExceptOne(workbench.getWorkspace(), getBrowser().getSelectedItemIds(), getRootItemId()); } - /** - * Update the items in the actionPopup based on the selected item and the ActionPopup availability configuration. - * This method can be overriden to implement custom conditions diverging from {@link #updateActionbar(info.magnolia.ui.actionbar.ActionbarPresenter)}. - */ - private void updateActionPopup(ActionPopup actionPopup) { - - actionPopup.removeAllItems(); - - BrowserSubAppDescriptor subAppDescriptor = (BrowserSubAppDescriptor) getSubAppContext().getSubAppDescriptor(); - WorkbenchDefinition workbench = subAppDescriptor.getWorkbench(); - ActionbarDefinition actionbarDefinition = subAppDescriptor.getActionbar(); - if (actionbarDefinition == null) { - return; - } - List sections = actionbarDefinition.getSections(); - - try { - String workbenchRootItemId = JcrItemUtil.getItemId(workbench.getWorkspace(), workbench.getPath()); - List selectedItemIds = getBrowser().getSelectedItemIds(); - List items = getJcrItemsExceptOne(workbench.getWorkspace(), selectedItemIds, workbenchRootItemId); - - // Figure out which section to show, only one - ActionbarSectionDefinition sectionDefinition = getVisibleSection(sections, items); + @Override + protected boolean verifyAvailability(Item item, AvailabilityDefinition availability) { + if (item instanceof JcrItemAdapter) { + JcrItemAdapter jcrItemAdapter = (JcrItemAdapter)item; - // If there no section matched the selection we just hide everything - if (sectionDefinition == null) { - return; + // If its a property we display it only if the properties property is set + if (!jcrItemAdapter.isNode()) { + return availability.isProperties(); } - // Evaluate availability of each action within the section - ContextMenu.ContextMenuItem menuItem = null; - for (ActionbarGroupDefinition groupDefinition : sectionDefinition.getGroups()) { - for (ActionbarItemDefinition itemDefinition : groupDefinition.getItems()) { - - String actionName = itemDefinition.getName(); - menuItem = addActionPopupItem(subAppDescriptor, actionPopup, itemDefinition, items); - menuItem.setEnabled(actionExecutor.isAvailable(actionName, items.toArray(new Item[items.size()]))); - } - - // Add group separator. - if (menuItem != null) { - menuItem.setSeparatorVisible(true); + // If node is selected and the section is available for nodes + if (availability.isNodes()) { + // if no node type defined, the for all node types + if (availability.getNodeTypes().isEmpty()) { + return true; } - } - if (menuItem != null) { - menuItem.setSeparatorVisible(false); - } - } catch (RepositoryException e) { - log.error("Failed to updated actionbar", e); - } - } - - /** - * Add an additional menu item on the actionPopup. - */ - private ContextMenu.ContextMenuItem addActionPopupItem(BrowserSubAppDescriptor subAppDescriptor, ActionPopup actionPopup, ActionbarItemDefinition itemDefinition, List items) { - String actionName = itemDefinition.getName(); - - ActionDefinition action = subAppDescriptor.getActions().get(actionName); - String label = action.getLabel(); - String iconFontCode = ActionPopup.ICON_FONT_CODE + action.getIcon(); - ExternalResource iconFontResource = new ExternalResource(iconFontCode); - ContextMenu.ContextMenuItem menuItem = actionPopup.addItem(label, iconFontResource); - // Set data variable so that the event handler can determine which action to launch. - menuItem.setData(actionName); - - return menuItem; - } - - /** - * Update the items in the actionbar based on the selected item and the action availability configuration. - * This method can be overriden to implement custom conditions diverging from {@link #updateActionPopup(info.magnolia.ui.vaadin.actionbar.ActionPopup)}. - * - * @see #restoreBrowser(BrowserLocation) - * @see #locationChanged(Location) - * @see ActionbarPresenter - */ - public void updateActionbar(ActionbarPresenter actionbar) { - - BrowserSubAppDescriptor subAppDescriptor = (BrowserSubAppDescriptor) getSubAppContext().getSubAppDescriptor(); - WorkbenchDefinition workbench = subAppDescriptor.getWorkbench(); - ActionbarDefinition actionbarDefinition = subAppDescriptor.getActionbar(); - if (actionbarDefinition == null) { - return; - } - List sections = actionbarDefinition.getSections(); - - try { - String workbenchRootItemId = JcrItemUtil.getItemId(workbench.getWorkspace(), workbench.getPath()); - List selectedItemIds = getBrowser().getSelectedItemIds(); - List items = getJcrItemsExceptOne(workbench.getWorkspace(), selectedItemIds, workbenchRootItemId); - - // Figure out which section to show, only one - ActionbarSectionDefinition sectionDefinition = getVisibleSection(sections, items); - - // If there no section matched the selection we just hide everything - if (sectionDefinition == null) { - for (ActionbarSectionDefinition section : sections) { - actionbar.hideSection(section.getName()); + // else the node must match at least one of the configured node types + for (String nodeType : availability.getNodeTypes()) { + try { + if (NodeUtil.isNodeType((Node) jcrItemAdapter.getJcrItem(), nodeType)) { + return true; + } + } catch (RepositoryException e) { + continue; + } } - return; - } - // Hide all other sections - for (ActionbarSectionDefinition section : sections) { - if (section != sectionDefinition) { - actionbar.hideSection(section.getName()); - } } - // Show our section - actionbar.showSection(sectionDefinition.getName()); - - // Evaluate availability of each action within the section - for (ActionbarGroupDefinition groupDefinition : sectionDefinition.getGroups()) { - for (ActionbarItemDefinition itemDefinition : groupDefinition.getItems()) { - - String actionName = itemDefinition.getName(); - if (actionExecutor.isAvailable(actionName, items.toArray(new Item[items.size()]))) { - actionbar.enable(actionName); - } else { - actionbar.disable(actionName); - } - } - } - } catch (RepositoryException e) { - log.error("Failed to updated actionbar", e); - for (ActionbarSectionDefinition section : sections) { - actionbar.hideSection(section.getName()); - } } - } - private ActionbarSectionDefinition getVisibleSection(List sections, List items) throws RepositoryException { - for (ActionbarSectionDefinition section : sections) { - if (isSectionVisible(section, items)) - return section; - } - return null; + return super.verifyAvailability(item, availability); } - private boolean isSectionVisible(ActionbarSectionDefinition section, List items) throws RepositoryException { - AvailabilityDefinition availability = section.getAvailability(); - - // Validate that the user has all required roles - only once - if (!availability.getAccess().hasAccess(MgnlContext.getUser())) { - return false; - } - - if (items != null) { - // section must be visible for all items - for (Item item : items) { - if (!isSectionVisible(section, item)) { - return false; - } + @Override + protected void applySelectionToLocation(BrowserLocation location, Object selectedId) { + try { + location.updateNodePath(""); + javax.jcr.Item selected = JcrItemUtil.getJcrItem(getWorkbench().getWorkspace(), JcrItemUtil.parseNodeIdentifier(String.valueOf(selectedId))); + if (selected == null) { + // nothing is selected at the moment + } else { + location.updateNodePath(StringUtils.removeStart(selected.getPath(), "/".equals(workbenchRoot) ? "" : workbenchRoot)); } + } catch (RepositoryException e) { + //log.warn("Could not get jcrItem with itemId " + event.getFirstItemId() + " from workspace " + event.getWorkspace(), e); + log.warn("Could not updated the location", e); } - return true; } - private boolean isSectionVisible(ActionbarSectionDefinition section, Item item) throws RepositoryException { - AvailabilityDefinition availability = section.getAvailability(); - - // if a rule class is set, verify it first - if ((availability.getRuleClass() != null)) { - // if the rule class cannot be instantiated, or the rule returns false - AvailabilityRule rule = componentProvider.newInstance(availability.getRuleClass()); - if (rule == null || !rule.isAvailable(item)) { - return false; - } - } - - // If this is the root item we display the section only if the root property is set - if (item == null) { - return availability.isRoot(); - } - - // If its a property we display it only if the properties property is set - if (!item.isNode()) { - return availability.isProperties(); - } - - // If node is selected and the section is available for nodes - if (availability.isNodes()) { - // if no node type defined, the for all node types - if (availability.getNodeTypes().isEmpty()) { - return true; - } - // else the node must match at least one of the configured node types - for (String nodeType : availability.getNodeTypes()) { - if (NodeUtil.isNodeType((Node) item, nodeType)) { - return true; - } - } - + public static List getItemsExceptOne(final String workspaceName, List ids, Object itemIdToExclude) { + List items = new ArrayList(); + if (itemIdToExclude == null) { + return items; } - return false; - } - protected final BrowserPresenter getBrowser() { - return browser; - } - - /** - * The default implementation selects the path in the current workspace and updates the available actions in the actionbar. - */ - @Override - public void locationChanged(final Location location) { - super.locationChanged(location); - restoreBrowser(BrowserLocation.wrap(location)); - } - - /** - * Wraps the current DefaultLocation in a {@link BrowserLocation}. Providing getter and setters for used parameters. - */ - @Override - public BrowserLocation getCurrentLocation() { - return BrowserLocation.wrap(super.getCurrentLocation()); - } - - /* - * Registers general purpose handlers for the following events: - *
    - *
  • {@link ItemSelectedEvent} - *
  • {@link ViewTypeChangedEvent} - *
  • {@link SearchEvent} - *
- */ - private void registerSubAppEventsHandlers(final EventBus subAppEventBus, final BrowserSubApp subApp) { - final ActionbarPresenter actionbar = subApp.getBrowser().getActionbarPresenter(); - subAppEventBus.addHandler(SelectionChangedEvent.class, new SelectionChangedEvent.Handler() { - - @Override - public void onSelectionChanged(SelectionChangedEvent event) { - BrowserLocation location = getCurrentLocation(); + for (Object itemId : ids) { + if (!itemIdToExclude.equals(itemId)) { try { - Item selected = JcrItemUtil.getJcrItem(event.getWorkspace(), JcrItemUtil.parseNodeIdentifier(event.getFirstItemId())); - if (selected == null) { - // nothing is selected at the moment - location.updateNodePath(""); + javax.jcr.Item jcrItem = JcrItemUtil.getJcrItem(workspaceName, String.valueOf(itemId)); + if (jcrItem.isNode()) { + items.add(new JcrNodeAdapter((Node)jcrItem)); } else { - location.updateNodePath(StringUtils.removeStart(selected.getPath(), "/".equals(workbenchRoot) ? "" : workbenchRoot)); + items.add(new JcrPropertyAdapter((Property)jcrItem)); } - } catch (RepositoryException e) { - log.warn("Could not get jcrItem with itemId " + event.getFirstItemId() + " from workspace " + event.getWorkspace(), e); - } - getAppContext().updateSubAppLocation(getSubAppContext(), location); - updateActionbar(actionbar); - } - }); - subAppEventBus.addHandler(ItemRightClickedEvent.class, new ItemRightClickedEvent.Handler() { - - @Override - public void onItemRightClicked(ItemRightClickedEvent event) { - String absItemPath; - try { - absItemPath = event.getItem().getJcrItem().getPath(); - - showActionPopup(absItemPath, event.getClickX(), event.getClickY()); } catch (RepositoryException e) { - log.warn("Could not get jcrItem with itemId " + event.getItemId() + " from workspace " + event.getWorkspace(), e); + e.printStackTrace(); } } - }); - - subAppEventBus.addHandler(ViewTypeChangedEvent.class, new ViewTypeChangedEvent.Handler() { - - @Override - public void onViewChanged(ViewTypeChangedEvent event) { - BrowserLocation location = getCurrentLocation(); - // remove search term from fragment when switching back - if (location.getViewType().equals(SearchPresenterDefinition.VIEW_TYPE) - && !event.getViewType().equals(SearchPresenterDefinition.VIEW_TYPE)) { - location.updateQuery(""); - } - location.updateViewType(event.getViewType()); - getAppContext().updateSubAppLocation(getSubAppContext(), location); - updateActionbar(actionbar); - } - }); - - subAppEventBus.addHandler(SearchEvent.class, new SearchEvent.Handler() { - - @Override - public void onSearch(SearchEvent event) { - BrowserLocation location = getCurrentLocation(); - if (StringUtils.isNotBlank(event.getSearchExpression())) { - location.updateViewType(SearchPresenterDefinition.VIEW_TYPE); - } - location.updateQuery(event.getSearchExpression()); - getAppContext().updateSubAppLocation(getSubAppContext(), location); - updateActionbar(actionbar); - } - }); - } - - public static List getJcrItemsExceptOne(final String workspaceName, List ids, String itemIdToExclude) { - List items = JcrItemUtil.getJcrItems(workspaceName, ids); - if (itemIdToExclude == null) { - return items; - } - for (int i = 0; i < items.size(); i++) { - try { - if (itemIdToExclude.equals(JcrItemUtil.getItemId(items.get(i)))) { - items.set(i, null); - } - } catch (RepositoryException e) { - log.debug("Cannot get item ID for item [{}].", items.get(i)); - } } return items; } diff --git a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserSubAppBase.java b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserSubAppBase.java new file mode 100644 index 0000000..389639f --- /dev/null +++ b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserSubAppBase.java @@ -0,0 +1,501 @@ +/** + * This file Copyright (c) 2012-2013 Magnolia International + * Ltd. (http://www.magnolia-cms.com). All rights reserved. + * + * + * This file is dual-licensed under both the Magnolia + * Network Agreement and the GNU General Public License. + * You may elect to use one or the other of these licenses. + * + * This file is distributed in the hope that it will be + * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. + * Redistribution, except as permitted by whichever of the GPL + * or MNA you select, is prohibited. + * + * 1. For the GPL license (GPL), you can redistribute and/or + * modify this file under the terms of the GNU General + * Public License, Version 3, as published by the Free Software + * Foundation. You should have received a copy of the GNU + * General Public License, Version 3 along with this program; + * if not, write to the Free Software Foundation, Inc., 51 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 2. For the Magnolia Network Agreement (MNA), this file + * and the accompanying materials are made available under the + * terms of the MNA which accompanies this distribution, and + * is available at http://www.magnolia-cms.com/mna.html + * + * Any modifications to this file must keep this entire header + * intact. + * + */ +package info.magnolia.ui.contentapp.browser; + +import info.magnolia.context.MgnlContext; +import info.magnolia.event.EventBus; +import info.magnolia.objectfactory.ComponentProvider; +import info.magnolia.ui.actionbar.ActionbarPresenter; +import info.magnolia.ui.actionbar.definition.ActionbarDefinition; +import info.magnolia.ui.actionbar.definition.ActionbarGroupDefinition; +import info.magnolia.ui.actionbar.definition.ActionbarItemDefinition; +import info.magnolia.ui.actionbar.definition.ActionbarSectionDefinition; +import info.magnolia.ui.api.action.ActionDefinition; +import info.magnolia.ui.api.action.ActionExecutor; +import info.magnolia.ui.api.app.SubAppContext; +import info.magnolia.ui.api.app.SubAppEventBus; +import info.magnolia.ui.api.availability.AvailabilityDefinition; +import info.magnolia.ui.api.availability.AvailabilityRule; +import info.magnolia.ui.api.location.Location; +import info.magnolia.ui.contentapp.ContentSubAppView; +import info.magnolia.ui.framework.app.BaseSubApp; +import info.magnolia.ui.vaadin.actionbar.ActionPopup; +import info.magnolia.ui.workbench.definition.WorkbenchDefinition; +import info.magnolia.ui.workbench.event.ItemRightClickedEvent; +import info.magnolia.ui.workbench.event.SearchEvent; +import info.magnolia.ui.workbench.event.SelectionChangedEvent; +import info.magnolia.ui.workbench.event.ViewTypeChangedEvent; +import info.magnolia.ui.workbench.search.SearchPresenterDefinition; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Named; + +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.vaadin.peter.contextmenu.ContextMenu; + +import com.vaadin.data.Item; +import com.vaadin.server.ExternalResource; + +/** + * Base implementation of a content subApp. A content subApp displays a collection of data represented inside a {@link info.magnolia.ui.workbench.ContentView} created by the {@link info.magnolia.ui.workbench.WorkbenchPresenter}. + * + *
+ *  

+ * This class Provides sensible implementation for services shared by all content subApps. + * Out-of-the-box it will handle the following: + *

+ * + *
    + *
  • location updates when switching views, selecting items or performing searches: see {@link #locationChanged(Location)} + *
  • restoring the browser app status when i.e. coming from a bookmark: see {@link #start(Location)} + *
+ * In order to perform those tasks this class registers non-overridable handlers for the following events: + *
    + *
  • {@link SelectionChangedEvent} + *
  • {@link ViewTypeChangedEvent} + *
  • {@link SearchEvent} + *
+ * Subclasses can augment the default behavior and perform additional tasks by overriding the following methods: + *
    + *
  • {@link #onSubAppStart()} + *
  • {@link #locationChanged(Location)} + *
  • {@link #updateActionbar(ActionbarPresenter)} + *
+ *
+ * + * @see BrowserPresenter + * @see info.magnolia.ui.contentapp.ContentSubAppView + * @see info.magnolia.ui.contentapp.ContentApp + * @see BrowserLocation + */ +public abstract class BrowserSubAppBase extends BaseSubApp { + + private static final Logger log = LoggerFactory.getLogger(BrowserSubApp.class); + + private final BrowserPresenterBase browser; + private final EventBus subAppEventBus; + private ActionExecutor actionExecutor; + private ComponentProvider componentProvider; + protected String workbenchRoot; + + @Inject + public BrowserSubAppBase(ActionExecutor actionExecutor, final SubAppContext subAppContext, final ContentSubAppView view, final BrowserPresenterBase browser, final @Named(SubAppEventBus.NAME) EventBus subAppEventBus, final ComponentProvider componentProvider) { + super(subAppContext, view); + if (subAppContext == null || view == null || browser == null || subAppEventBus == null) { + throw new IllegalArgumentException("Constructor does not allow for null args. Found SubAppContext = " + subAppContext + ", ContentSubAppView = " + view + ", BrowserPresenter = " + browser + ", EventBus = " + subAppEventBus); + } + this.browser = browser; + this.subAppEventBus = subAppEventBus; + this.actionExecutor = actionExecutor; + this.componentProvider = componentProvider; + this.workbenchRoot = getWorkbench().getPath(); + } + + protected abstract Object ensureSelection(String urlFragmentPath, WorkbenchDefinition workbench); + + protected Object getRootItemId() { + return browser.getWorkbenchPresenter().resolveWorkbenchRoot(); + } + + + //TODO JCRFREE - consider Actionbar availability interface that would encapsulate JCR/Non-JCR availability logic + protected boolean verifyAvailability(Item item, AvailabilityDefinition availability) { + // If this is the root item we display the section only if the root property is set + if (item == null) { + return availability.isRoot(); + } + + return false; + } + + protected abstract void applySelectionToLocation(BrowserLocation location, Object selectedId); + + /** + * Performs some routine tasks needed by all content subapps before the view is displayed. + * The tasks are: + *
    + *
  • setting the current location + *
  • setting the browser view + *
  • restoring the browser status: see {@link #restoreBrowser(BrowserLocation)} + *
  • calling {@link #onSubAppStart()} a hook-up method subclasses can override to perform additional work. + *
+ */ + @Override + public ContentSubAppView start(final Location location) { + BrowserLocation l = BrowserLocation.wrap(location); + super.start(l); + getView().setContentView(browser.start()); + restoreBrowser(l); + registerSubAppEventsHandlers(subAppEventBus, this); + + return getView(); + } + + /** + * Restores the browser status based on the information available in the location object. This is used e.g. when starting a subapp based on a + * bookmark. I.e. given a bookmark containing the following URI fragment + *

+ * {@code + * #app:myapp:browser;/foo/bar:list + * } + *

+ * this method will select the path /foo/bar in the workspace used by the app, set the view type as list and finally update the available actions. + *

+ * In case of a search view the URI fragment will look similar to the following one {@code + * #app:myapp:browser;/:search:qux + * } + *

+ * then this method will select the root path, set the view type as search, perform a search for "qux" in the workspace used by the app and finally update the available actions. + * + * @see BrowserSubApp#updateActionbar(ActionbarPresenter) + * @see BrowserSubApp#start(Location) + * @see Location + */ + protected void restoreBrowser(final BrowserLocation location) { + String path = ("/".equals(workbenchRoot) ? "" : workbenchRoot) + location.getNodePath(); + String viewType = location.getViewType(); + + if (!getBrowser().hasViewType(viewType)) { + if (!StringUtils.isBlank(viewType)) { + log.warn("Unknown view type [{}], returning to default view type.", viewType); + } + viewType = getBrowser().getDefaultViewType(); + location.updateViewType(viewType); + getAppContext().updateSubAppLocation(getSubAppContext(), location); + } + String query = location.getQuery(); + + BrowserSubAppDescriptor subAppDescriptor = (BrowserSubAppDescriptor) getSubAppContext().getSubAppDescriptor(); + + Object itemId = ensureSelection(path, subAppDescriptor.getWorkbench()); + if (itemId != null) { + getBrowser().resync(Arrays.asList(itemId), viewType, query); + updateActionbar(getBrowser().getActionbarPresenter()); + } + } + + + /** + * Show the actionPopup for the specified item at the specified coordinates. + */ + public void showActionPopup(Object itemId, int x, int y) { + + // If there's no actionbar configured we don't want to show an empty action popup + BrowserSubAppDescriptor subAppDescriptor = (BrowserSubAppDescriptor) getSubAppContext().getSubAppDescriptor(); + ActionbarDefinition actionbarDefinition = subAppDescriptor.getActionbar(); + if (actionbarDefinition == null) { + return; + } + + ActionPopup actionPopup = browser.getView().getActionPopup(); + + updateActionPopup(actionPopup); + actionPopup.open(x, y); + } + + /** + * Update the items in the actionPopup based on the selected item and the ActionPopup availability configuration. + * This method can be overriden to implement custom conditions diverging from {@link #updateActionbar(info.magnolia.ui.actionbar.ActionbarPresenter)}. + */ + private void updateActionPopup(ActionPopup actionPopup) { + + actionPopup.removeAllItems(); + + BrowserSubAppDescriptor subAppDescriptor = (BrowserSubAppDescriptor) getSubAppContext().getSubAppDescriptor(); + WorkbenchDefinition workbench = subAppDescriptor.getWorkbench(); + ActionbarDefinition actionbarDefinition = subAppDescriptor.getActionbar(); + if (actionbarDefinition == null) { + return; + } + List sections = actionbarDefinition.getSections(); + + Object workbenchRootItemId = getRootItemId(); + List selectedItemIds = getBrowser().getSelectedItemIds(); + List items = getSelectedItems(); + + // Figure out which section to show, only one + ActionbarSectionDefinition sectionDefinition = getVisibleSection(sections, items); + + // If there no section matched the selection we just hide everything + if (sectionDefinition == null) { + return; + } + + // Evaluate availability of each action within the section + ContextMenu.ContextMenuItem menuItem = null; + for (ActionbarGroupDefinition groupDefinition : sectionDefinition.getGroups()) { + for (ActionbarItemDefinition itemDefinition : groupDefinition.getItems()) { + + String actionName = itemDefinition.getName(); + menuItem = addActionPopupItem(subAppDescriptor, actionPopup, itemDefinition, items); + menuItem.setEnabled(actionExecutor.isAvailable(actionName, items.toArray(new Item[items.size()]))); + } + + // Add group separator. + if (menuItem != null) { + menuItem.setSeparatorVisible(true); + } + } + if (menuItem != null) { + menuItem.setSeparatorVisible(false); + } + } + + protected List getSelectedItems() { + return browser.getSelectedItems(); + } + + /** + * Add an additional menu item on the actionPopup. + */ + private ContextMenu.ContextMenuItem addActionPopupItem(BrowserSubAppDescriptor subAppDescriptor, ActionPopup actionPopup, ActionbarItemDefinition itemDefinition, List items) { + String actionName = itemDefinition.getName(); + + ActionDefinition action = subAppDescriptor.getActions().get(actionName); + String label = action.getLabel(); + String iconFontCode = ActionPopup.ICON_FONT_CODE + action.getIcon(); + ExternalResource iconFontResource = new ExternalResource(iconFontCode); + ContextMenu.ContextMenuItem menuItem = actionPopup.addItem(label, iconFontResource); + // Set data variable so that the event handler can determine which action to launch. + menuItem.setData(actionName); + + return menuItem; + } + + /** + * Update the items in the actionbar based on the selected item and the action availability configuration. + * This method can be overriden to implement custom conditions diverging from {@link #updateActionPopup(info.magnolia.ui.vaadin.actionbar.ActionPopup)}. + * + * @see #restoreBrowser(BrowserLocation) + * @see #locationChanged(Location) + * @see ActionbarPresenter + */ + public void updateActionbar(ActionbarPresenter actionbar) { + + BrowserSubAppDescriptor subAppDescriptor = (BrowserSubAppDescriptor) getSubAppContext().getSubAppDescriptor(); + WorkbenchDefinition workbench = subAppDescriptor.getWorkbench(); + ActionbarDefinition actionbarDefinition = subAppDescriptor.getActionbar(); + if (actionbarDefinition == null) { + return; + } + List sections = actionbarDefinition.getSections(); + + Object workbenchRootItemId = getRootItemId(); + List selectedItemIds = getBrowser().getSelectedItemIds(); + List items = getSelectedItems(); + + // Figure out which section to show, only one + ActionbarSectionDefinition sectionDefinition = getVisibleSection(sections, items); + + // If there no section matched the selection we just hide everything + if (sectionDefinition == null) { + for (ActionbarSectionDefinition section : sections) { + actionbar.hideSection(section.getName()); + } + return; + } + + // Hide all other sections + for (ActionbarSectionDefinition section : sections) { + if (section != sectionDefinition) { + actionbar.hideSection(section.getName()); + } + } + + // Show our section + actionbar.showSection(sectionDefinition.getName()); + + // Evaluate availability of each action within the section + for (ActionbarGroupDefinition groupDefinition : sectionDefinition.getGroups()) { + for (ActionbarItemDefinition itemDefinition : groupDefinition.getItems()) { + + String actionName = itemDefinition.getName(); + if (actionExecutor.isAvailable(actionName, items.toArray(new Item[items.size()]))) { + actionbar.enable(actionName); + } else { + actionbar.disable(actionName); + } + } + } + + } + + + + private ActionbarSectionDefinition getVisibleSection(List sections, List items) { + for (ActionbarSectionDefinition section : sections) { + if (isSectionVisible(section, items)) + return section; + } + return null; + } + + private boolean isSectionVisible(ActionbarSectionDefinition section, List items) { + AvailabilityDefinition availability = section.getAvailability(); + + // Validate that the user has all required roles - only once + if (!availability.getAccess().hasAccess(MgnlContext.getUser())) { + return false; + } + + if (items != null) { + // section must be visible for all items + for (Item item : items) { + if (!isSectionVisible(section, item)) { + return false; + } + } + } + return true; + } + + protected boolean isSectionVisible(ActionbarSectionDefinition section, Item item) { + AvailabilityDefinition availability = section.getAvailability(); + + // if a rule class is set, verify it first + if ((availability.getRuleClass() != null)) { + // if the rule class cannot be instantiated, or the rule returns false + AvailabilityRule rule = componentProvider.newInstance(availability.getRuleClass()); + if (rule == null || !rule.isAvailable(item)) { + return false; + } + } + + return verifyAvailability(item, availability); + } + + + protected final BrowserPresenterBase getBrowser() { + return browser; + } + + /** + * The default implementation selects the path in the current workspace and updates the available actions in the actionbar. + */ + @Override + public void locationChanged(final Location location) { + super.locationChanged(location); + restoreBrowser(BrowserLocation.wrap(location)); + } + + /** + * Wraps the current DefaultLocation in a {@link BrowserLocation}. Providing getter and setters for used parameters. + */ + @Override + public BrowserLocation getCurrentLocation() { + return BrowserLocation.wrap(super.getCurrentLocation()); + } + + /* + * Registers general purpose handlers for the following events: + *
    + *
  • {@link ItemSelectedEvent} + *
  • {@link ViewTypeChangedEvent} + *
  • {@link SearchEvent} + *
+ */ + private void registerSubAppEventsHandlers(final EventBus subAppEventBus, final BrowserSubAppBase subApp) { + final ActionbarPresenter actionbar = subApp.getBrowser().getActionbarPresenter(); + subAppEventBus.addHandler(SelectionChangedEvent.class, new SelectionChangedEvent.Handler() { + + @Override + public void onSelectionChanged(SelectionChangedEvent event) { + handleSelectionChange(event.getItemIds(), actionbar); + } + }); + + subAppEventBus.addHandler(ItemRightClickedEvent.class, new ItemRightClickedEvent.Handler() { + + @Override + public void onItemRightClicked(ItemRightClickedEvent event) { + showActionPopup(event.getItemId(), event.getClickX(), event.getClickY()); + } + }); + + subAppEventBus.addHandler(ViewTypeChangedEvent.class, new ViewTypeChangedEvent.Handler() { + + @Override + public void onViewChanged(ViewTypeChangedEvent event) { + BrowserLocation location = getCurrentLocation(); + // remove search term from fragment when switching back + if (location.getViewType().equals(SearchPresenterDefinition.VIEW_TYPE) + && !event.getViewType().equals(SearchPresenterDefinition.VIEW_TYPE)) { + location.updateQuery(""); + } + location.updateViewType(event.getViewType()); + getAppContext().updateSubAppLocation(getSubAppContext(), location); + updateActionbar(actionbar); + } + }); + + subAppEventBus.addHandler(SearchEvent.class, new SearchEvent.Handler() { + + @Override + public void onSearch(SearchEvent event) { + BrowserLocation location = getCurrentLocation(); + if (StringUtils.isNotBlank(event.getSearchExpression())) { + location.updateViewType(SearchPresenterDefinition.VIEW_TYPE); + } + location.updateQuery(event.getSearchExpression()); + getAppContext().updateSubAppLocation(getSubAppContext(), location); + updateActionbar(actionbar); + } + }); + } + + /** + * TODO call applySelectionToLocation with proper parameters (convert id to string value) + * @param selectionIds + * @param actionbar + */ + private void handleSelectionChange(Set selectionIds, ActionbarPresenter actionbar) { + BrowserLocation location = getCurrentLocation(); + applySelectionToLocation(location, selectionIds.isEmpty() ? "" : selectionIds.iterator().next()); + getAppContext().updateSubAppLocation(getSubAppContext(), location); + updateActionbar(actionbar); + + } + + + protected WorkbenchDefinition getWorkbench() { + return ((BrowserSubAppDescriptor) getSubAppContext().getSubAppDescriptor()).getWorkbench(); + } + +} diff --git a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserView.java b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserView.java index 28f5ba3..306198a 100644 --- a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserView.java +++ b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserView.java @@ -33,9 +33,9 @@ */ package info.magnolia.ui.contentapp.browser; +import info.magnolia.ui.actionbar.ActionbarView; import info.magnolia.ui.api.view.View; import info.magnolia.ui.vaadin.actionbar.ActionPopup; -import info.magnolia.ui.vaadin.actionbar.ActionbarView; import info.magnolia.ui.workbench.WorkbenchView; import com.vaadin.ui.ComponentContainer; diff --git a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserViewImpl.java b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserViewImpl.java index 4c13aa3..4ea3c79 100644 --- a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserViewImpl.java +++ b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/BrowserViewImpl.java @@ -33,8 +33,8 @@ */ package info.magnolia.ui.contentapp.browser; +import info.magnolia.ui.actionbar.ActionbarView; import info.magnolia.ui.vaadin.actionbar.ActionPopup; -import info.magnolia.ui.vaadin.actionbar.ActionbarView; import info.magnolia.ui.workbench.WorkbenchView; import org.vaadin.peter.contextmenu.ContextMenu; diff --git a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/beanbrowser/BeanBrowserPresenter.java b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/beanbrowser/BeanBrowserPresenter.java new file mode 100644 index 0000000..abfb562 --- /dev/null +++ b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/beanbrowser/BeanBrowserPresenter.java @@ -0,0 +1,81 @@ +/** + * This file Copyright (c) 2013 Magnolia International + * Ltd. (http://www.magnolia-cms.com). All rights reserved. + * + * + * This file is dual-licensed under both the Magnolia + * Network Agreement and the GNU General Public License. + * You may elect to use one or the other of these licenses. + * + * This file is distributed in the hope that it will be + * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. + * Redistribution, except as permitted by whichever of the GPL + * or MNA you select, is prohibited. + * + * 1. For the GPL license (GPL), you can redistribute and/or + * modify this file under the terms of the GNU General + * Public License, Version 3, as published by the Free Software + * Foundation. You should have received a copy of the GNU + * General Public License, Version 3 along with this program; + * if not, write to the Free Software Foundation, Inc., 51 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 2. For the Magnolia Network Agreement (MNA), this file + * and the accompanying materials are made available under the + * terms of the MNA which accompanies this distribution, and + * is available at http://www.magnolia-cms.com/mna.html + * + * Any modifications to this file must keep this entire header + * intact. + * + */ +package info.magnolia.ui.contentapp.browser.beanbrowser; + +import info.magnolia.event.EventBus; +import info.magnolia.ui.actionbar.ActionbarPresenter; +import info.magnolia.ui.api.action.ActionExecutor; +import info.magnolia.ui.api.app.SubAppContext; +import info.magnolia.ui.api.app.SubAppEventBus; +import info.magnolia.ui.api.event.AdmincentralEventBus; +import info.magnolia.ui.contentapp.browser.BrowserPresenterBase; +import info.magnolia.ui.contentapp.browser.BrowserView; +import info.magnolia.ui.workbench.beanworkbench.BeanWorkbenchPresenter; +import info.magnolia.ui.workbench.event.ItemEditedEvent; + +import javax.inject.Inject; +import javax.inject.Named; + +/** + * Created with IntelliJ IDEA. + * User: sasha + * Date: 05/02/14 + * Time: 01:09 + * To change this template use File | Settings | File Templates. + */ +public class BeanBrowserPresenter extends BrowserPresenterBase { + + @Inject + public BeanBrowserPresenter( + ActionExecutor actionExecutor, + SubAppContext subAppContext, + BrowserView view, + @Named(AdmincentralEventBus.NAME) EventBus admincentralEventBus, + @Named(SubAppEventBus.NAME) EventBus subAppEventBus, + ActionbarPresenter actionbarPresenter, + BeanWorkbenchPresenter workbenchPresenter) { + super(actionExecutor, subAppContext, view, admincentralEventBus, subAppEventBus, actionbarPresenter, workbenchPresenter); + } + + @Override + protected void editItem(ItemEditedEvent event) { + + } + + @Override + protected Object getPreviewImageForId(Object itemId) { + return null; + } + +} diff --git a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/beanbrowser/BeanBrowserSubApp.java b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/beanbrowser/BeanBrowserSubApp.java new file mode 100644 index 0000000..46c299f --- /dev/null +++ b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/browser/beanbrowser/BeanBrowserSubApp.java @@ -0,0 +1,75 @@ +/** + * This file Copyright (c) 2013 Magnolia International + * Ltd. (http://www.magnolia-cms.com). All rights reserved. + * + * + * This file is dual-licensed under both the Magnolia + * Network Agreement and the GNU General Public License. + * You may elect to use one or the other of these licenses. + * + * This file is distributed in the hope that it will be + * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. + * Redistribution, except as permitted by whichever of the GPL + * or MNA you select, is prohibited. + * + * 1. For the GPL license (GPL), you can redistribute and/or + * modify this file under the terms of the GNU General + * Public License, Version 3, as published by the Free Software + * Foundation. You should have received a copy of the GNU + * General Public License, Version 3 along with this program; + * if not, write to the Free Software Foundation, Inc., 51 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 2. For the Magnolia Network Agreement (MNA), this file + * and the accompanying materials are made available under the + * terms of the MNA which accompanies this distribution, and + * is available at http://www.magnolia-cms.com/mna.html + * + * Any modifications to this file must keep this entire header + * intact. + * + */ +package info.magnolia.ui.contentapp.browser.beanbrowser; + +import info.magnolia.event.EventBus; +import info.magnolia.objectfactory.ComponentProvider; +import info.magnolia.ui.api.action.ActionExecutor; +import info.magnolia.ui.api.app.SubAppContext; +import info.magnolia.ui.api.app.SubAppEventBus; +import info.magnolia.ui.contentapp.ContentSubAppView; +import info.magnolia.ui.contentapp.browser.BrowserLocation; +import info.magnolia.ui.contentapp.browser.BrowserSubAppBase; +import info.magnolia.ui.workbench.definition.WorkbenchDefinition; + +import java.io.File; + +import javax.inject.Inject; +import javax.inject.Named; + +/** + * Created with IntelliJ IDEA. + * User: sasha + * Date: 04/02/14 + * Time: 23:46 + * To change this template use File | Settings | File Templates. + */ +public class BeanBrowserSubApp extends BrowserSubAppBase { + + @Inject + public BeanBrowserSubApp(ActionExecutor actionExecutor, SubAppContext subAppContext, ContentSubAppView view, BeanBrowserPresenter browser, @Named(SubAppEventBus.NAME) EventBus subAppEventBus, ComponentProvider componentProvider) { + super(actionExecutor, subAppContext, view, browser, subAppEventBus, componentProvider); + } + + @Override + protected Object ensureSelection(String urlFragmentPath, WorkbenchDefinition workbench) { + return getBrowser().getWorkbenchPresenter().getItemFor(new File("/Users/sasha/test")); + } + + @Override + protected void applySelectionToLocation(BrowserLocation location, Object selectedId) { + + } + +} diff --git a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/detail/DetailEditorPresenter.java b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/detail/DetailEditorPresenter.java index bd5c8ed..d03ffb8 100644 --- a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/detail/DetailEditorPresenter.java +++ b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/detail/DetailEditorPresenter.java @@ -39,7 +39,7 @@ import info.magnolia.i18nsystem.SimpleTranslator; import info.magnolia.jcr.util.SessionUtil; import info.magnolia.objectfactory.Components; import info.magnolia.ui.actionbar.ActionbarPresenter; -import info.magnolia.ui.api.action.ActionDefinition; +import info.magnolia.ui.actionbar.ActionbarView; import info.magnolia.ui.api.action.ActionExecutionException; import info.magnolia.ui.api.action.ActionExecutor; import info.magnolia.ui.api.app.AppContext; @@ -48,7 +48,6 @@ import info.magnolia.ui.api.message.Message; import info.magnolia.ui.api.message.MessageType; import info.magnolia.ui.api.view.View; import info.magnolia.ui.contentapp.definition.EditorDefinition; -import info.magnolia.ui.vaadin.actionbar.ActionbarView; import info.magnolia.ui.vaadin.integration.jcr.JcrNewNodeAdapter; import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter; @@ -145,7 +144,7 @@ public class DetailEditorPresenter implements DetailEditorView.Listener, Actionb view.setItemView(itemView); actionbarPresenter.setListener(this); - ActionbarView actionbar = actionbarPresenter.start(subAppDescriptor.getActionbar()); + ActionbarView actionbar = actionbarPresenter.start(subAppDescriptor.getActionbar(), subAppDescriptor.getActions()); view.setActionbarView(actionbar); @@ -189,16 +188,4 @@ public class DetailEditorPresenter implements DetailEditorView.Listener, Actionb } } - @Override - public String getLabel(String actionName) { - ActionDefinition actionDefinition = actionExecutor.getActionDefinition(actionName); - return actionDefinition != null ? actionDefinition.getLabel() : null; - } - - @Override - public String getIcon(String actionName) { - ActionDefinition actionDefinition = actionExecutor.getActionDefinition(actionName); - return actionDefinition != null ? actionDefinition.getIcon() : null; - } - } diff --git a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/detail/DetailEditorView.java b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/detail/DetailEditorView.java index 42eae23..a9486a1 100644 --- a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/detail/DetailEditorView.java +++ b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/detail/DetailEditorView.java @@ -33,8 +33,8 @@ */ package info.magnolia.ui.contentapp.detail; +import info.magnolia.ui.actionbar.ActionbarView; import info.magnolia.ui.api.view.View; -import info.magnolia.ui.vaadin.actionbar.ActionbarView; import com.vaadin.ui.ComponentContainer; diff --git a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/detail/DetailEditorViewImpl.java b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/detail/DetailEditorViewImpl.java index 63c8688..87f00f9 100644 --- a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/detail/DetailEditorViewImpl.java +++ b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/detail/DetailEditorViewImpl.java @@ -33,15 +33,16 @@ */ package info.magnolia.ui.contentapp.detail; -import com.vaadin.ui.Component; -import com.vaadin.ui.CssLayout; -import com.vaadin.ui.HorizontalLayout; +import info.magnolia.ui.actionbar.ActionbarView; import info.magnolia.ui.api.view.View; -import info.magnolia.ui.vaadin.actionbar.ActionbarView; import java.util.EnumMap; import java.util.Map; +import com.vaadin.ui.Component; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.HorizontalLayout; + /** * Implementation of {@link DetailEditorView}. * Holds the {@link ActionbarView} and {@link DetailView} Currently lacking some functionality planned. See MGNLUI-154. diff --git a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/detail/DetailPresenter.java b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/detail/DetailPresenter.java index 1fcf8f6..5905023 100644 --- a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/detail/DetailPresenter.java +++ b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/detail/DetailPresenter.java @@ -159,7 +159,7 @@ public class DetailPresenter implements EditorCallback, EditorValidator, ActionL boolean isJcrItemAdapter = (item instanceof JcrItemAdapter); for (FormActionItemDefinition editorAction : editorActions) { ActionDefinition def = subAppActions.get(editorAction.getName()); - if (def != null && (!isJcrItemAdapter || (isJcrItemAdapter && executor.isAvailable(editorAction.getName(), ((JcrItemAdapter) item).getJcrItem())))) { + if (def != null && (!isJcrItemAdapter || (isJcrItemAdapter && executor.isAvailable(editorAction.getName(), item)))) { filteredActions.add(def); } else { log.debug("Action is configured for an editor but not configured for sub-app: " + editorAction.getName()); diff --git a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/field/LinkFieldSelectionFactory.java b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/field/LinkFieldSelectionFactory.java index e45db52..f800d1f 100644 --- a/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/field/LinkFieldSelectionFactory.java +++ b/magnolia-ui-contentapp/src/main/java/info/magnolia/ui/contentapp/field/LinkFieldSelectionFactory.java @@ -102,7 +102,8 @@ public class LinkFieldSelectionFactory extends AbstractFieldFactory { @Override public void onSelectionChanged(SelectionChangedEvent event) { try { - JcrItemAdapter firstItem = event.getFirstItem(); + JcrNodeAdapter firstItem = (JcrNodeAdapter) new JcrNodeAdapter(NodeUtil.getNodeByIdentifier(presenter.getWorkspace(), String.valueOf(event.getFirstItemId()))); Item value = !"/".equals(firstItem.getJcrItem().getPath()) ? firstItem : new NullItem(); setValue(value, false); } catch (RepositoryException e) { diff --git a/magnolia-ui-contentapp/src/main/resources/META-INF/magnolia/ui-contentapp.xml b/magnolia-ui-contentapp/src/main/resources/META-INF/magnolia/ui-contentapp.xml index fe02552..4ef0518 100644 --- a/magnolia-ui-contentapp/src/main/resources/META-INF/magnolia/ui-contentapp.xml +++ b/magnolia-ui-contentapp/src/main/resources/META-INF/magnolia/ui-contentapp.xml @@ -77,6 +77,11 @@ + info.magnolia.ui.contentapp.browser.beanbrowser.BeanBrowserPresenter + info.magnolia.ui.contentapp.browser.beanbrowser.BeanBrowserPresenter + + + info.magnolia.ui.contentapp.detail.DetailEditorPresenter info.magnolia.ui.contentapp.detail.DetailEditorPresenter diff --git a/magnolia-ui-contentapp/src/test/java/info/magnolia/ui/contentapp/ContentSubAppTest.java b/magnolia-ui-contentapp/src/test/java/info/magnolia/ui/contentapp/ContentSubAppTest.java index 608791d..88932d7 100644 --- a/magnolia-ui-contentapp/src/test/java/info/magnolia/ui/contentapp/ContentSubAppTest.java +++ b/magnolia-ui-contentapp/src/test/java/info/magnolia/ui/contentapp/ContentSubAppTest.java @@ -37,7 +37,6 @@ import static org.mockito.Matchers.*; import static org.mockito.Mockito.*; import info.magnolia.event.EventBus; -import info.magnolia.i18nsystem.SimpleTranslator; import info.magnolia.objectfactory.ComponentProvider; import info.magnolia.ui.actionbar.ActionbarPresenter; import info.magnolia.ui.api.action.ActionExecutor; @@ -45,7 +44,6 @@ import info.magnolia.ui.api.app.AppContext; import info.magnolia.ui.api.app.SubAppContext; import info.magnolia.ui.api.availability.AbstractAvailabilityRule; import info.magnolia.ui.contentapp.browser.BrowserPresenter; -import info.magnolia.ui.contentapp.browser.BrowserSubApp; import javax.jcr.Item; @@ -79,8 +77,8 @@ public class ContentSubAppTest { view = mock(ContentSubAppView.class); workbench = mock(BrowserPresenter.class); - ActionbarPresenter actionbar = new ActionbarPresenter(mock(SimpleTranslator.class)); - when(workbench.getActionbarPresenter()).thenReturn(actionbar); + ActionbarPresenter actionbarPresenter = mock(ActionbarPresenter.class); + when(workbench.getActionbarPresenter()).thenReturn(actionbarPresenter); subAppEventBus = mock(EventBus.class); this.subApp = new DummyContentSubApp(null, subAppContext, view, workbench, subAppEventBus); diff --git a/magnolia-ui-contentapp/src/test/java/info/magnolia/ui/contentapp/browser/BrowserSubAppTest.java b/magnolia-ui-contentapp/src/test/java/info/magnolia/ui/contentapp/browser/BrowserSubAppTest.java index 950ae0f..75d4d20 100644 --- a/magnolia-ui-contentapp/src/test/java/info/magnolia/ui/contentapp/browser/BrowserSubAppTest.java +++ b/magnolia-ui-contentapp/src/test/java/info/magnolia/ui/contentapp/browser/BrowserSubAppTest.java @@ -42,7 +42,6 @@ import info.magnolia.cms.security.operations.ConfiguredAccessDefinition; import info.magnolia.context.MgnlContext; import info.magnolia.event.EventBus; import info.magnolia.i18nsystem.I18nizer; -import info.magnolia.i18nsystem.SimpleTranslator; import info.magnolia.jcr.util.NodeTypes; import info.magnolia.jcr.util.NodeUtil; import info.magnolia.jcr.util.PropertyUtil; @@ -55,7 +54,6 @@ import info.magnolia.test.MgnlTestCase; import info.magnolia.test.mock.MockWebContext; import info.magnolia.test.mock.jcr.MockSession; import info.magnolia.ui.actionbar.ActionbarPresenter; -import info.magnolia.ui.actionbar.definition.ActionbarDefinition; import info.magnolia.ui.actionbar.definition.ActionbarItemDefinition; import info.magnolia.ui.actionbar.definition.ConfiguredActionbarDefinition; import info.magnolia.ui.actionbar.definition.ConfiguredActionbarGroupDefinition; @@ -65,22 +63,14 @@ import info.magnolia.ui.api.action.AbstractActionExecutor; import info.magnolia.ui.api.action.ActionDefinition; import info.magnolia.ui.api.action.ConfiguredActionDefinition; import info.magnolia.ui.api.app.AppContext; -import info.magnolia.ui.api.app.SubApp; import info.magnolia.ui.api.app.SubAppContext; -import info.magnolia.ui.api.app.SubAppDescriptor; import info.magnolia.ui.api.availability.AvailabilityDefinition; import info.magnolia.ui.api.availability.ConfiguredAvailabilityDefinition; import info.magnolia.ui.api.availability.IsDeletedRule; import info.magnolia.ui.api.location.DefaultLocation; import info.magnolia.ui.api.location.Location; -import info.magnolia.ui.api.overlay.AlertCallback; -import info.magnolia.ui.api.overlay.ConfirmationCallback; -import info.magnolia.ui.api.overlay.MessageStyleType; -import info.magnolia.ui.api.overlay.NotificationCallback; -import info.magnolia.ui.api.overlay.OverlayCloser; -import info.magnolia.ui.api.view.View; import info.magnolia.ui.contentapp.ContentSubAppView; -import info.magnolia.ui.vaadin.actionbar.ActionbarView; +import info.magnolia.ui.framework.app.SubAppContextImpl; import info.magnolia.ui.vaadin.integration.jcr.JcrItemUtil; import info.magnolia.ui.workbench.definition.ConfiguredWorkbenchDefinition; @@ -128,9 +118,13 @@ public class BrowserSubAppTest extends MgnlTestCase { private EventBus subAppEventBus; private ContentSubAppView view; private BrowserPresenter browserPresenter; - private TestActionbarPresenter testActionbarPresenter; private ComponentProvider componentProvider; + private ActionbarPresenter actionbarPresenter; + private final Set visibleSections = new HashSet(); + private final Set enabledActions = new HashSet(); + + // actions private ConfiguredActionDefinition actAlways; private ConfiguredActionDefinition actRootOnly; @@ -207,7 +201,7 @@ public class BrowserSubAppTest extends MgnlTestCase { subAppContext.setAppContext(mockAppContext); // 3. some location with unknown viewType - DefaultLocation location = new DefaultLocation("app", "someApp", "someContentApp", "/some/node:unknownView"); + Location location = new DefaultLocation("app", "someApp", "someContentApp", "/some/node:unknownView"); subAppContext.setLocation(location); // WHEN @@ -258,10 +252,10 @@ public class BrowserSubAppTest extends MgnlTestCase { subApp.updateActionbar(browserPresenter.getActionbarPresenter()); // THEN - assertEquals(1, testActionbarPresenter.visibleSections.size()); - assertTrue(testActionbarPresenter.visibleSections.contains(SECTION_TO_SHOW)); - assertTrue(testActionbarPresenter.enabledActions.contains(ALWAYS)); - assertTrue(testActionbarPresenter.enabledActions.contains(ROOT_ONLY)); + assertEquals(1, visibleSections.size()); + assertTrue(visibleSections.contains(SECTION_TO_SHOW)); + assertTrue(enabledActions.contains(ALWAYS)); + assertTrue(enabledActions.contains(ROOT_ONLY)); } @Test @@ -275,11 +269,11 @@ public class BrowserSubAppTest extends MgnlTestCase { subApp.updateActionbar(browserPresenter.getActionbarPresenter()); // THEN - assertEquals(1, testActionbarPresenter.visibleSections.size()); - assertTrue(testActionbarPresenter.visibleSections.contains(SECTION_TO_SHOW)); - assertTrue(testActionbarPresenter.visibleSections.contains(SECTION_TO_SHOW)); - assertTrue(testActionbarPresenter.enabledActions.contains(ALWAYS)); - assertFalse(testActionbarPresenter.enabledActions.contains(ROOT_ONLY)); + assertEquals(1, visibleSections.size()); + assertTrue(visibleSections.contains(SECTION_TO_SHOW)); + assertTrue(visibleSections.contains(SECTION_TO_SHOW)); + assertTrue(enabledActions.contains(ALWAYS)); + assertFalse(enabledActions.contains(ROOT_ONLY)); } @Test @@ -293,11 +287,11 @@ public class BrowserSubAppTest extends MgnlTestCase { subApp.updateActionbar(browserPresenter.getActionbarPresenter()); // THEN - assertEquals(1, testActionbarPresenter.visibleSections.size()); - assertTrue(testActionbarPresenter.visibleSections.contains(SECTION_TO_SHOW)); - assertTrue(testActionbarPresenter.visibleSections.contains(SECTION_TO_SHOW)); - assertTrue(testActionbarPresenter.enabledActions.contains(ALWAYS)); - assertFalse(testActionbarPresenter.enabledActions.contains(ROOT_ONLY)); + assertEquals(1, visibleSections.size()); + assertTrue(visibleSections.contains(SECTION_TO_SHOW)); + assertTrue(visibleSections.contains(SECTION_TO_SHOW)); + assertTrue(enabledActions.contains(ALWAYS)); + assertFalse(enabledActions.contains(ROOT_ONLY)); } // HELPER METHODS @@ -313,24 +307,25 @@ public class BrowserSubAppTest extends MgnlTestCase { } private void initBrowser() { - ConfiguredActionbarDefinition definition = new ConfiguredActionbarDefinition(); - definition.addSection(sectionToShow); - definition.addSection(sectionToHide); - testActionbarPresenter = new TestActionbarPresenter(); - browserPresenter = mock(BrowserPresenter.class); - when(browserPresenter.getActionbarPresenter()).thenReturn(testActionbarPresenter); - - testActionbarPresenter.setListener(browserPresenter); - testActionbarPresenter.start(definition); ConfiguredWorkbenchDefinition wbDef = new ConfiguredWorkbenchDefinition(); wbDef.setWorkspace(WORKSPACE); wbDef.setPath(ROOT_PATH); + + ConfiguredActionbarDefinition definition = new ConfiguredActionbarDefinition(); + definition.addSection(sectionToShow); + definition.addSection(sectionToHide); + ConfiguredBrowserSubAppDescriptor descriptor = new ConfiguredBrowserSubAppDescriptor(); descriptor.setWorkbench(wbDef); descriptor.setActionbar(definition); + subAppContext = new SubAppContextImpl(descriptor, null); + + actionbarPresenter = mock(ActionbarPresenter.class); + mockActionbarPresenter(); - subAppContext = new TestSubAppContext(descriptor); + browserPresenter = mock(BrowserPresenter.class); + when(browserPresenter.getActionbarPresenter()).thenReturn(actionbarPresenter); } private void initActionbarGroupsAndSections() { @@ -427,151 +422,55 @@ public class BrowserSubAppTest extends MgnlTestCase { return new SimpleActionExecutor(componentProvider); } - private static class TestActionbarPresenter extends ActionbarPresenter { - public TestActionbarPresenter() { - super(mock(SimpleTranslator.class)); - } + private void mockActionbarPresenter() { - public Set visibleSections; - public Set enabledActions; + doAnswer(new VarargStubAnswer() { - @Override - public ActionbarView start(ActionbarDefinition def) { - visibleSections = new HashSet(); - enabledActions = new HashSet(); - return super.start(def); - } + @Override + void stub(String... args) { + visibleSections.addAll(Arrays.asList(args)); + } + }).when(actionbarPresenter).showSection((String[]) anyVararg()); - @Override - public void showSection(String... sectionNames) { - super.showSection(sectionNames); - visibleSections.addAll(Arrays.asList(sectionNames)); - } + doAnswer(new VarargStubAnswer() { - @Override - public void hideSection(String... sectionNames) { - super.hideSection(sectionNames); - for (String section : sectionNames) { - visibleSections.remove(section); + @Override + void stub(String... args) { + visibleSections.removeAll(Arrays.asList(args)); } - } + }).when(actionbarPresenter).hideSection((String[]) anyVararg()); - @Override - public void enable(String... actionNames) { - super.enable(actionNames); - enabledActions.addAll(Arrays.asList(actionNames)); - } + doAnswer(new VarargStubAnswer() { - @Override - public void disable(String... actionNames) { - super.disable(actionNames); - enabledActions.removeAll(Arrays.asList(actionNames)); - } + @Override + void stub(String... args) { + enabledActions.addAll(Arrays.asList(args)); + } + }).when(actionbarPresenter).enable((String[]) anyVararg()); + + doAnswer(new VarargStubAnswer() { + + @Override + void stub(String... args) { + enabledActions.removeAll(Arrays.asList(args)); + } + }).when(actionbarPresenter).disable((String[]) anyVararg()); } /** - * Basic Empty implementation of {@link SubAppContext} for test purpose. + * Utility mockito {@link Answer} to help stubbing methods with String varargs. */ - public static class TestSubAppContext implements SubAppContext { - - private Location location; - private AppContext appContext; - private SubAppDescriptor descriptor; - - public TestSubAppContext(SubAppDescriptor descriptor) { - this.descriptor = descriptor; - } - - @Override - public OverlayCloser openOverlay(View view) { - return null; - } - - @Override - public OverlayCloser openOverlay(View view, ModalityLevel modalityLevel) { - return null; - } - - @Override - public void openAlert(MessageStyleType type, View viewToShow, String confirmButtonText, AlertCallback cb) { - } - - @Override - public void openAlert(MessageStyleType type, String title, String body, String confirmButtonText, AlertCallback cb) { - } + private static abstract class VarargStubAnswer implements Answer { - @Override - public void openConfirmation(MessageStyleType type, View viewToShow, String confirmButtonText, String cancelButtonText, boolean cancelIsDefault, ConfirmationCallback cb) { - } - - @Override - public void openConfirmation(MessageStyleType type, String title, String body, String confirmButtonText, String cancelButtonText, boolean cancelIsDefault, ConfirmationCallback cb) { - } - - @Override - public void openNotification(MessageStyleType type, boolean doesTimeout, View viewToShow) { - } - - @Override - public void openNotification(MessageStyleType type, boolean doesTimeout, String title) { - } + abstract void stub(String... args); @Override - public void openNotification(MessageStyleType type, boolean doesTimeout, String title, String linkText, NotificationCallback cb) { - } - - @Override - public String getSubAppId() { - return null; - } - - @Override - public SubApp getSubApp() { + public Void answer(InvocationOnMock invocation) throws Throwable { + Object[] args = invocation.getArguments(); + String[] stringArgs = Arrays.copyOf(args, args.length, String[].class); + stub(stringArgs); return null; } - - @Override - public Location getLocation() { - return location; - } - - @Override - public AppContext getAppContext() { - return appContext; - } - - @Override - public SubAppDescriptor getSubAppDescriptor() { - return descriptor; - } - - @Override - public void setAppContext(AppContext appContext) { - this.appContext = appContext; - } - - @Override - public void setLocation(Location location) { - this.location = location; - } - - @Override - public void setSubApp(SubApp subApp) { - } - - @Override - public void setInstanceId(String instanceId) { - } - - @Override - public String getInstanceId() { - return null; - } - - @Override - public void close() { - } - } } diff --git a/magnolia-ui-dialog/src/main/java/info/magnolia/ui/dialog/formdialog/FormDialogPresenterImpl.java b/magnolia-ui-dialog/src/main/java/info/magnolia/ui/dialog/formdialog/FormDialogPresenterImpl.java index 36fe3d5..6f536b7 100644 --- a/magnolia-ui-dialog/src/main/java/info/magnolia/ui/dialog/formdialog/FormDialogPresenterImpl.java +++ b/magnolia-ui-dialog/src/main/java/info/magnolia/ui/dialog/formdialog/FormDialogPresenterImpl.java @@ -169,7 +169,7 @@ public class FormDialogPresenterImpl extends BaseDialogPresenter implements Form List result = new LinkedList(); boolean isJcrItemAdapter = (item instanceof JcrItemAdapter); for (ActionDefinition action : getDefinition().getActions().values()) { - if (!isJcrItemAdapter || getExecutor().isAvailable(action.getName(), ((JcrItemAdapter) item).getJcrItem())) { + if (!isJcrItemAdapter || getExecutor().isAvailable(action.getName(), item)) { result.add(action); } } diff --git a/magnolia-ui-form/src/main/java/info/magnolia/ui/form/action/SaveFormAction.java b/magnolia-ui-form/src/main/java/info/magnolia/ui/form/action/SaveFormAction.java index de6c5f6..1b3017f 100644 --- a/magnolia-ui-form/src/main/java/info/magnolia/ui/form/action/SaveFormAction.java +++ b/magnolia-ui-form/src/main/java/info/magnolia/ui/form/action/SaveFormAction.java @@ -35,12 +35,12 @@ package info.magnolia.ui.form.action; import info.magnolia.cms.core.Path; import info.magnolia.jcr.util.NodeUtil; -import info.magnolia.ui.api.ModelConstants; import info.magnolia.ui.api.action.AbstractAction; import info.magnolia.ui.api.action.ActionExecutionException; import info.magnolia.ui.form.EditorCallback; import info.magnolia.ui.form.EditorValidator; import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter; +import info.magnolia.ui.vaadin.integration.jcr.ModelConstants; import javax.jcr.Node; import javax.jcr.Property; diff --git a/magnolia-ui-framework/src/main/resources/META-INF/magnolia/ui-framework.xml b/magnolia-ui-framework/src/main/resources/META-INF/magnolia/ui-framework.xml index a659a71..00bf44b 100644 --- a/magnolia-ui-framework/src/main/resources/META-INF/magnolia/ui-framework.xml +++ b/magnolia-ui-framework/src/main/resources/META-INF/magnolia/ui-framework.xml @@ -340,6 +340,12 @@ info.magnolia.ui.workbench.WorkbenchPresenter info.magnolia.ui.workbench.WorkbenchPresenter + + + info.magnolia.ui.workbench.beanworkbench.BeanWorkbenchPresenter + info.magnolia.ui.workbench.beanworkbench.BeanWorkbenchPresenter + + info.magnolia.ui.workbench.WorkbenchView info.magnolia.ui.workbench.WorkbenchViewImpl diff --git a/magnolia-ui-framework/src/test/java/info/magnolia/ui/framework/action/ConfirmationActionTest.java b/magnolia-ui-framework/src/test/java/info/magnolia/ui/framework/action/ConfirmationActionTest.java index 921b382..79daba3 100644 --- a/magnolia-ui-framework/src/test/java/info/magnolia/ui/framework/action/ConfirmationActionTest.java +++ b/magnolia-ui-framework/src/test/java/info/magnolia/ui/framework/action/ConfirmationActionTest.java @@ -73,7 +73,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -import javax.jcr.Item; import javax.jcr.Node; import javax.jcr.Session; @@ -81,6 +80,8 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; +import com.vaadin.data.Item; + /** * Test covering execution of {@link ConfirmationAction}. */ diff --git a/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/MediaEditorPresenterFactoryImpl.java b/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/MediaEditorPresenterFactoryImpl.java index 18b71de..03682c1 100644 --- a/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/MediaEditorPresenterFactoryImpl.java +++ b/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/MediaEditorPresenterFactoryImpl.java @@ -139,22 +139,16 @@ public class MediaEditorPresenterFactoryImpl implements MediaEditorPresenterFact @Override public MediaEditorPresenter getPresenterByDefinition(MediaEditorDefinition definition) { ComponentProvider mediaEditorComponentProvider = createMediaEditorComponentProvider(); + + AppContext appContext = mediaEditorComponentProvider.getComponent(AppContext.class); MediaEditorView view = mediaEditorComponentProvider.getComponent(MediaEditorView.class); - ActionbarPresenter actionbarPresenter = new ActionbarPresenter(i18n); ActionExecutor mediaActionExecutor = mediaEditorComponentProvider.getComponent(ActionExecutor.class); + ((MediaEditorActionExecutor) mediaActionExecutor).setDef(definition); + + ActionbarPresenter actionBarPresenter = mediaEditorComponentProvider.getComponent(ActionbarPresenter.class); DialogPresenter dialogPresenter = new BaseDialogPresenter(mediaEditorComponentProvider, mediaActionExecutor, new BaseDialogViewImpl(), this.i18nizer, i18n); - AppContext appContext = mediaEditorComponentProvider.getComponent(AppContext.class); - MediaEditorPresenter mediaEditorPresenter = - new MediaEditorPresenterImpl( - definition, - eventBus, - view, - actionbarPresenter, - dialogPresenter, - appContext, - i18n); + MediaEditorPresenter mediaEditorPresenter = new MediaEditorPresenterImpl(definition, eventBus, view, actionBarPresenter, dialogPresenter, appContext, i18n); - ((MediaEditorActionExecutor) mediaActionExecutor).setDef(definition); mediaEditorPresenter.setActionExecutor(mediaActionExecutor); return mediaEditorPresenter; } diff --git a/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/MediaEditorPresenterImpl.java b/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/MediaEditorPresenterImpl.java index cf74fb5..3881788 100644 --- a/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/MediaEditorPresenterImpl.java +++ b/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/MediaEditorPresenterImpl.java @@ -37,7 +37,7 @@ import info.magnolia.event.EventBus; import info.magnolia.event.HandlerRegistration; import info.magnolia.i18nsystem.SimpleTranslator; import info.magnolia.ui.actionbar.ActionbarPresenter; -import info.magnolia.ui.api.action.ActionDefinition; +import info.magnolia.ui.actionbar.ActionbarView; import info.magnolia.ui.api.action.ActionExecutionException; import info.magnolia.ui.api.action.ActionExecutor; import info.magnolia.ui.api.app.AppContext; @@ -54,7 +54,6 @@ import info.magnolia.ui.mediaeditor.event.MediaEditorCompletedEvent; import info.magnolia.ui.mediaeditor.event.MediaEditorCompletedEvent.CompletionType; import info.magnolia.ui.mediaeditor.event.MediaEditorCompletedEvent.Handler; import info.magnolia.ui.mediaeditor.event.MediaEditorInternalEvent; -import info.magnolia.ui.vaadin.actionbar.ActionbarView; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -118,9 +117,8 @@ public class MediaEditorPresenterImpl implements MediaEditorPresenter, Actionbar @Override public View start(final InputStream stream) { try { - final ActionbarView actionbar = actionbarPresenter.start(definition.getActionBar()); + final ActionbarView actionbar = actionbarPresenter.start(definition.getActionBar(), definition.getActions()); final DialogView dialogView = dialogPresenter.start(new ConfiguredDialogDefinition(), appContext); - this.dataSource = new EditHistoryTrackingPropertyImpl(IOUtils.toByteArray(stream), i18n); this.dataSource.setListener(this); view.setActionBar(actionbar); @@ -180,18 +178,6 @@ public class MediaEditorPresenterImpl implements MediaEditorPresenter, Actionbar } @Override - public String getLabel(String actionName) { - ActionDefinition actionDefinition = actionExecutor.getActionDefinition(actionName); - return actionDefinition != null ? actionDefinition.getLabel() : null; - } - - @Override - public String getIcon(String actionName) { - ActionDefinition actionDefinition = actionExecutor.getActionDefinition(actionName); - return actionDefinition != null ? actionDefinition.getIcon() : null; - } - - @Override public MediaEditorDefinition getDefinition() { return definition; } diff --git a/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/MediaEditorView.java b/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/MediaEditorView.java index a6b3331..9dcf9b4 100644 --- a/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/MediaEditorView.java +++ b/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/MediaEditorView.java @@ -37,7 +37,7 @@ import com.vaadin.ui.Component; import info.magnolia.ui.api.view.View; import info.magnolia.ui.dialog.DialogView; import info.magnolia.ui.mediaeditor.field.MediaField; -import info.magnolia.ui.vaadin.actionbar.ActionbarView; +import info.magnolia.ui.actionbar.ActionbarView; /** * Interface of media editor view. diff --git a/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/MediaEditorViewImpl.java b/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/MediaEditorViewImpl.java index c28cb05..388592b 100644 --- a/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/MediaEditorViewImpl.java +++ b/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/MediaEditorViewImpl.java @@ -33,25 +33,26 @@ */ package info.magnolia.ui.mediaeditor; -import com.vaadin.ui.Component; -import com.vaadin.ui.CustomComponent; -import com.vaadin.ui.HorizontalLayout; +import info.magnolia.ui.actionbar.ActionbarView; import info.magnolia.ui.api.view.View; import info.magnolia.ui.dialog.DialogView; import info.magnolia.ui.mediaeditor.field.MediaField; -import info.magnolia.ui.vaadin.actionbar.ActionbarView; + +import com.vaadin.ui.Component; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.HorizontalLayout; /** * Skeleton implementation of the media editor UI. Contains an actionbar and a dialog laid out horizontally. */ public class MediaEditorViewImpl extends CustomComponent implements MediaEditorView { - + private DialogView dialog; - + private ActionbarView actionbar; - + private HorizontalLayout root = new HorizontalLayout(); - + public MediaEditorViewImpl() { addStyleName("v-media-editor"); setCompositionRoot(root); @@ -59,7 +60,7 @@ public class MediaEditorViewImpl extends CustomComponent implements MediaEditorV root.setSizeFull(); root.setSpacing(true); } - + @Override public Component asVaadinComponent() { return this; diff --git a/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/action/ViewImageAction.java b/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/action/ViewImageAction.java index dc97a05..3bad9c3 100644 --- a/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/action/ViewImageAction.java +++ b/magnolia-ui-mediaeditor/src/main/java/info/magnolia/ui/mediaeditor/action/ViewImageAction.java @@ -34,6 +34,7 @@ package info.magnolia.ui.mediaeditor.action; import info.magnolia.event.EventBus; +import info.magnolia.ui.actionbar.ActionbarView; import info.magnolia.i18nsystem.SimpleTranslator; import info.magnolia.ui.api.action.ActionExecutionException; import info.magnolia.ui.dialog.actionarea.ActionListener; @@ -45,7 +46,6 @@ import info.magnolia.ui.mediaeditor.event.MediaEditorInternalEvent.EventType; import info.magnolia.ui.mediaeditor.field.MediaField; import info.magnolia.ui.mediaeditor.field.image.ViewImageField; import info.magnolia.ui.mediaeditor.provider.MediaEditorActionDefinition; -import info.magnolia.ui.vaadin.actionbar.ActionbarView; import info.magnolia.ui.vaadin.gwt.client.actionbar.shared.ActionbarItem; import java.util.ArrayList; diff --git a/magnolia-ui-vaadin-common-widgets/pom.xml b/magnolia-ui-vaadin-common-widgets/pom.xml index 0278345..94c8db7 100644 --- a/magnolia-ui-vaadin-common-widgets/pom.xml +++ b/magnolia-ui-vaadin-common-widgets/pom.xml @@ -20,7 +20,7 @@ info.magnolia.ui - magnolia-ui-vaadin-integration + magnolia-ui-api com.vaadin diff --git a/magnolia-ui-vaadin-common-widgets/src/main/java/info/magnolia/ui/vaadin/actionbar/Actionbar.java b/magnolia-ui-vaadin-common-widgets/src/main/java/info/magnolia/ui/vaadin/actionbar/Actionbar.java index 3f355f6..0e41957 100644 --- a/magnolia-ui-vaadin-common-widgets/src/main/java/info/magnolia/ui/vaadin/actionbar/Actionbar.java +++ b/magnolia-ui-vaadin-common-widgets/src/main/java/info/magnolia/ui/vaadin/actionbar/Actionbar.java @@ -38,6 +38,7 @@ import info.magnolia.ui.vaadin.gwt.client.actionbar.rpc.ActionbarServerRpc; import info.magnolia.ui.vaadin.gwt.client.actionbar.shared.ActionbarItem; import info.magnolia.ui.vaadin.gwt.client.actionbar.shared.ActionbarSection; +import java.lang.reflect.Method; import java.util.Collection; import java.util.Iterator; import java.util.Map; @@ -45,29 +46,30 @@ import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.vaadin.event.ConnectorEventListener; import com.vaadin.server.Resource; import com.vaadin.server.ThemeResource; import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.Component; +import com.vaadin.util.ReflectTools; /** * The Actionbar widget, consisting of sections and groups of actions. */ -public class Actionbar extends AbstractComponent implements ActionbarView { +public class Actionbar extends AbstractComponent { private static final Logger log = LoggerFactory.getLogger(Actionbar.class); - private ActionbarView.Listener listener; - public Actionbar() { setSizeFull(); setWidth(null); setImmediate(true); - setOpened(true); + setOpen(true); registerRpc(new ActionbarServerRpc() { @Override public void onActionTriggered(String actionToken) { - listener.onActionbarItemClicked(actionToken); + fireEvent(new ActionTriggerEvent(Actionbar.this, actionToken)); } @Override @@ -77,7 +79,6 @@ public class Actionbar extends AbstractComponent implements ActionbarView { }); } - @Override public void setOpen(boolean isOpen) { getState().isOpen = isOpen; if (isOpen && !getStyleName().contains("open")) { @@ -89,25 +90,6 @@ public class Actionbar extends AbstractComponent implements ActionbarView { } @Override - public Actionbar asVaadinComponent() { - return this; - } - - @Override - public void setListener(ActionbarView.Listener listener) { - this.listener = listener; - } - - public void setOpened(boolean isOpen) { - getState().isOpen = isOpen; - if (isOpen) { - addStyleName("open"); - } else { - removeStyleName("open"); - } - } - - @Override protected ActionbarState getState() { return (ActionbarState) super.getState(); } @@ -119,7 +101,6 @@ public class Actionbar extends AbstractComponent implements ActionbarView { // ACTION BAR API /////////////////////////// - @Override public void addAction(ActionbarItem action, String sectionName) { ActionbarSection section = getState().sections.get(sectionName); if (section != null) { @@ -129,27 +110,23 @@ public class Actionbar extends AbstractComponent implements ActionbarView { } } - @Override public void removeAction(String actionName) { for (ActionbarSection section : getState().sections.values()) { section.removeAction(actionName); } } - @Override public void addSection(String sectionName, String caption) { getState().sections.put(sectionName, new ActionbarSection(sectionName, caption)); getState().sectionOrder.add(sectionName); setSectionVisible(sectionName, true); } - @Override public void removeSection(String sectionName) { getState().sectionOrder.remove(sectionName); getState().sections.remove(sectionName); } - @Override public void setSectionPreview(Resource previewResource, String sectionName) { setResource(sectionName, previewResource); setSectionVisible(sectionName, true); @@ -159,7 +136,6 @@ public class Actionbar extends AbstractComponent implements ActionbarView { return getState(false).sections; } - @Override public void setSectionVisible(String sectionName, boolean isVisible) { ActionbarSection section = getState().sections.get(sectionName); if (isVisible && section != null) { @@ -171,7 +147,6 @@ public class Actionbar extends AbstractComponent implements ActionbarView { } } - @Override public boolean isSectionVisible(String sectionName) { final Iterator it = getState(false).visibleSections.iterator(); boolean result = false; @@ -181,14 +156,12 @@ public class Actionbar extends AbstractComponent implements ActionbarView { return result; } - @Override public void setGroupEnabled(String groupName, boolean isEnabled) { for (ActionbarSection section : getState().sections.values()) { doSetGroupEnabled(section, groupName, isEnabled); } } - @Override public void setGroupEnabled(String groupName, String sectionName, boolean isEnabled) { doSetGroupEnabled(getState().sections.get(sectionName), groupName, isEnabled); } @@ -201,7 +174,6 @@ public class Actionbar extends AbstractComponent implements ActionbarView { } } - @Override public void setActionEnabled(String actionName, boolean isEnabled) { final Collection sections = getState().sections.values(); for (ActionbarSection section : sections) { @@ -209,7 +181,6 @@ public class Actionbar extends AbstractComponent implements ActionbarView { } } - @Override public void setActionEnabled(String sectionName, String actionName, boolean isEnabled) { ActionbarItem action = getState().sections.get(sectionName).getActions().get(actionName); if (action != null) { @@ -227,4 +198,42 @@ public class Actionbar extends AbstractComponent implements ActionbarView { public void registerActionIconResource(String actionName, ThemeResource iconResource) { setResource(actionName, iconResource); } + + // EVENTS AND LISTENERS + + public void addActionTriggerListener(ActionTriggerListener listener) { + addListener(ActionTriggerListener.EVENT_ID, ActionTriggerEvent.class, listener, ActionTriggerListener.EVENT_METHOD); + } + + public void removeActionTriggerListener(ActionTriggerListener listener) { + removeListener(ActionTriggerListener.EVENT_ID, ActionTriggerEvent.class, listener); + } + + /** + * The listener interface for triggering actions from the action bar. + */ + public interface ActionTriggerListener extends ConnectorEventListener { + + public static final String EVENT_ID = "at"; + public static final Method EVENT_METHOD = ReflectTools.findMethod(ActionTriggerListener.class, "actionTrigger", ActionTriggerEvent.class); + + public void actionTrigger(ActionTriggerEvent event); + } + + /** + * The event fired when triggering actions from the action bar. + */ + public static class ActionTriggerEvent extends Component.Event { + + private final String actionName; + + public ActionTriggerEvent(Component source, String actionName) { + super(source); + this.actionName = actionName; + } + + public String getActionName() { + return actionName; + } + } } diff --git a/magnolia-ui-vaadin-common-widgets/src/main/java/info/magnolia/ui/vaadin/actionbar/ActionbarView.java b/magnolia-ui-vaadin-common-widgets/src/main/java/info/magnolia/ui/vaadin/actionbar/ActionbarView.java deleted file mode 100644 index 7f5f0c6..0000000 --- a/magnolia-ui-vaadin-common-widgets/src/main/java/info/magnolia/ui/vaadin/actionbar/ActionbarView.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * This file Copyright (c) 2012-2013 Magnolia International - * Ltd. (http://www.magnolia-cms.com). All rights reserved. - * - * - * This file is dual-licensed under both the Magnolia - * Network Agreement and the GNU General Public License. - * You may elect to use one or the other of these licenses. - * - * This file is distributed in the hope that it will be - * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. - * Redistribution, except as permitted by whichever of the GPL - * or MNA you select, is prohibited. - * - * 1. For the GPL license (GPL), you can redistribute and/or - * modify this file under the terms of the GNU General - * Public License, Version 3, as published by the Free Software - * Foundation. You should have received a copy of the GNU - * General Public License, Version 3 along with this program; - * if not, write to the Free Software Foundation, Inc., 51 - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * 2. For the Magnolia Network Agreement (MNA), this file - * and the accompanying materials are made available under the - * terms of the MNA which accompanies this distribution, and - * is available at http://www.magnolia-cms.com/mna.html - * - * Any modifications to this file must keep this entire header - * intact. - * - */ -package info.magnolia.ui.vaadin.actionbar; - -import info.magnolia.ui.api.view.View; -import info.magnolia.ui.vaadin.gwt.client.actionbar.shared.ActionbarItem; - -import com.vaadin.server.Resource; - -/** - * Base interface for an action bar view. - */ -public interface ActionbarView extends View { - - void setListener(Listener listener); - - void addSection(String sectionName, String label); - - void removeSection(String sectionName); - - void setSectionPreview(Resource previewResource, String sectionName); - - void addAction(ActionbarItem action, String sectionName); - - void removeAction(String actionName); - - // ENABLE / DISABLE - void setActionEnabled(String actionName, boolean isEnabled); - - void setActionEnabled(String actionName, String sectionName, boolean isEnabled); - - void setGroupEnabled(String groupName, boolean isEnabled); - - void setGroupEnabled(String groupName, String sectionName, boolean isEnabled); - - // SHOW / HIDE SECTIONS - void setSectionVisible(String sectionName, boolean isVisible); - - boolean isSectionVisible(String sectionName); - - void setOpen(boolean isOpen); - - /** - * Base interface for an action bar listener. - */ - interface Listener { - - /** - * Event handler invoked on clicking an item in the action bar. - * - * @param actionToken the action token - */ - void onActionbarItemClicked(String actionToken); - } -} \ No newline at end of file diff --git a/magnolia-ui-vaadin-integration/pom.xml b/magnolia-ui-vaadin-integration/pom.xml index 35a6888..e6de7a5 100644 --- a/magnolia-ui-vaadin-integration/pom.xml +++ b/magnolia-ui-vaadin-integration/pom.xml @@ -35,14 +35,14 @@ magnolia-core - info.magnolia.ui - magnolia-ui-api - - com.google.code.gson gson + com.vaadin + vaadin-server + + javax.servlet servlet-api test diff --git a/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/AbstractJcrAdapter.java b/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/AbstractJcrAdapter.java index 35168f7..ee46139 100644 --- a/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/AbstractJcrAdapter.java +++ b/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/AbstractJcrAdapter.java @@ -33,8 +33,6 @@ */ package info.magnolia.ui.vaadin.integration.jcr; -import info.magnolia.ui.api.ModelConstants; - import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; diff --git a/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/AbstractJcrNodeAdapter.java b/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/AbstractJcrNodeAdapter.java index 13bbf1d..eacc95d 100644 --- a/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/AbstractJcrNodeAdapter.java +++ b/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/AbstractJcrNodeAdapter.java @@ -37,7 +37,6 @@ import info.magnolia.cms.core.Path; import info.magnolia.jcr.RuntimeRepositoryException; import info.magnolia.jcr.util.NodeUtil; import info.magnolia.jcr.util.PropertyUtil; -import info.magnolia.ui.api.ModelConstants; import java.util.HashMap; import java.util.LinkedHashMap; diff --git a/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/JcrNewNodeAdapter.java b/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/JcrNewNodeAdapter.java index 835fd4b..2fd26c9 100644 --- a/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/JcrNewNodeAdapter.java +++ b/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/JcrNewNodeAdapter.java @@ -34,7 +34,6 @@ package info.magnolia.ui.vaadin.integration.jcr; import info.magnolia.cms.core.Path; -import info.magnolia.ui.api.ModelConstants; import javax.jcr.Item; import javax.jcr.Node; diff --git a/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/JcrPropertyAdapter.java b/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/JcrPropertyAdapter.java index 37d0197..d2e66be 100644 --- a/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/JcrPropertyAdapter.java +++ b/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/JcrPropertyAdapter.java @@ -36,7 +36,6 @@ package info.magnolia.ui.vaadin.integration.jcr; import info.magnolia.cms.core.Path; import info.magnolia.jcr.RuntimeRepositoryException; import info.magnolia.jcr.util.PropertyUtil; -import info.magnolia.ui.api.ModelConstants; import java.util.Collection; import java.util.Collections; diff --git a/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/ModelConstants.java b/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/ModelConstants.java new file mode 100644 index 0000000..4475ca4 --- /dev/null +++ b/magnolia-ui-vaadin-integration/src/main/java/info/magnolia/ui/vaadin/integration/jcr/ModelConstants.java @@ -0,0 +1,45 @@ +/** + * This file Copyright (c) 2012-2013 Magnolia International + * Ltd. (http://www.magnolia-cms.com). All rights reserved. + * + * + * This file is dual-licensed under both the Magnolia + * Network Agreement and the GNU General Public License. + * You may elect to use one or the other of these licenses. + * + * This file is distributed in the hope that it will be + * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. + * Redistribution, except as permitted by whichever of the GPL + * or MNA you select, is prohibited. + * + * 1. For the GPL license (GPL), you can redistribute and/or + * modify this file under the terms of the GNU General + * Public License, Version 3, as published by the Free Software + * Foundation. You should have received a copy of the GNU + * General Public License, Version 3 along with this program; + * if not, write to the Free Software Foundation, Inc., 51 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 2. For the Magnolia Network Agreement (MNA), this file + * and the accompanying materials are made available under the + * terms of the MNA which accompanies this distribution, and + * is available at http://www.magnolia-cms.com/mna.html + * + * Any modifications to this file must keep this entire header + * intact. + * + */ +package info.magnolia.ui.vaadin.integration.jcr; + +/** + * Constants used UI Model layer and higher. + */ +public interface ModelConstants { + + /** + * Defines what value is used to indicate it is the name of {@link javax.jcr.Item} - not a property of a {@link javax.jcr.Node}. + */ + public static final String JCR_NAME = "jcrName"; +} diff --git a/magnolia-ui-vaadin-integration/src/test/java/info/magnolia/ui/vaadin/integration/jcr/AbstractJcrNodeAdapterTest.java b/magnolia-ui-vaadin-integration/src/test/java/info/magnolia/ui/vaadin/integration/jcr/AbstractJcrNodeAdapterTest.java index 92a7901..67e5d4e 100644 --- a/magnolia-ui-vaadin-integration/src/test/java/info/magnolia/ui/vaadin/integration/jcr/AbstractJcrNodeAdapterTest.java +++ b/magnolia-ui-vaadin-integration/src/test/java/info/magnolia/ui/vaadin/integration/jcr/AbstractJcrNodeAdapterTest.java @@ -40,7 +40,6 @@ import info.magnolia.context.MgnlContext; import info.magnolia.test.mock.MockContext; import info.magnolia.test.mock.jcr.MockNode; import info.magnolia.test.mock.jcr.MockSession; -import info.magnolia.ui.api.ModelConstants; import java.util.Collection; diff --git a/magnolia-ui-vaadin-integration/src/test/java/info/magnolia/ui/vaadin/integration/jcr/JcrNewNodeAdapterTest.java b/magnolia-ui-vaadin-integration/src/test/java/info/magnolia/ui/vaadin/integration/jcr/JcrNewNodeAdapterTest.java index 0f13e07..1299c74 100644 --- a/magnolia-ui-vaadin-integration/src/test/java/info/magnolia/ui/vaadin/integration/jcr/JcrNewNodeAdapterTest.java +++ b/magnolia-ui-vaadin-integration/src/test/java/info/magnolia/ui/vaadin/integration/jcr/JcrNewNodeAdapterTest.java @@ -39,7 +39,6 @@ import info.magnolia.cms.security.MgnlUser; import info.magnolia.context.MgnlContext; import info.magnolia.test.mock.MockContext; import info.magnolia.test.mock.jcr.MockSession; -import info.magnolia.ui.api.ModelConstants; import java.util.Collections; diff --git a/magnolia-ui-vaadin-integration/src/test/java/info/magnolia/ui/vaadin/integration/jcr/JcrNodeAdapterRepositoryTest.java b/magnolia-ui-vaadin-integration/src/test/java/info/magnolia/ui/vaadin/integration/jcr/JcrNodeAdapterRepositoryTest.java index 5996c57..bc4ec24 100644 --- a/magnolia-ui-vaadin-integration/src/test/java/info/magnolia/ui/vaadin/integration/jcr/JcrNodeAdapterRepositoryTest.java +++ b/magnolia-ui-vaadin-integration/src/test/java/info/magnolia/ui/vaadin/integration/jcr/JcrNodeAdapterRepositoryTest.java @@ -40,7 +40,6 @@ import info.magnolia.context.MgnlContext; import info.magnolia.jcr.util.PropertiesImportExport; import info.magnolia.repository.RepositoryConstants; import info.magnolia.test.RepositoryTestCase; -import info.magnolia.ui.api.ModelConstants; import java.util.Arrays; import java.util.HashSet; diff --git a/magnolia-ui-vaadin-integration/src/test/java/info/magnolia/ui/vaadin/integration/jcr/JcrPropertyAdapterTest.java b/magnolia-ui-vaadin-integration/src/test/java/info/magnolia/ui/vaadin/integration/jcr/JcrPropertyAdapterTest.java index e987e88..f097e2a 100644 --- a/magnolia-ui-vaadin-integration/src/test/java/info/magnolia/ui/vaadin/integration/jcr/JcrPropertyAdapterTest.java +++ b/magnolia-ui-vaadin-integration/src/test/java/info/magnolia/ui/vaadin/integration/jcr/JcrPropertyAdapterTest.java @@ -40,7 +40,6 @@ import info.magnolia.context.MgnlContext; import info.magnolia.test.mock.MockContext; import info.magnolia.test.mock.jcr.MockSession; import info.magnolia.test.mock.jcr.MockValue; -import info.magnolia.ui.api.ModelConstants; import java.util.Collection; diff --git a/magnolia-ui-vaadin-widgetset/src/main/java/info/magnolia/ui/vaadin/gwt/MagnoliaWidgetSet.gwt.xml b/magnolia-ui-vaadin-widgetset/src/main/java/info/magnolia/ui/vaadin/gwt/MagnoliaWidgetSet.gwt.xml index e482fb2..b1b8312 100644 --- a/magnolia-ui-vaadin-widgetset/src/main/java/info/magnolia/ui/vaadin/gwt/MagnoliaWidgetSet.gwt.xml +++ b/magnolia-ui-vaadin-widgetset/src/main/java/info/magnolia/ui/vaadin/gwt/MagnoliaWidgetSet.gwt.xml @@ -11,7 +11,8 @@ - + + diff --git a/magnolia-ui-vaadin-widgetset/src/main/resources/VAADIN/themes/admincentraltheme/shell.scss b/magnolia-ui-vaadin-widgetset/src/main/resources/VAADIN/themes/admincentraltheme/shell.scss index b7d3e11..8b1eea5 100644 --- a/magnolia-ui-vaadin-widgetset/src/main/resources/VAADIN/themes/admincentraltheme/shell.scss +++ b/magnolia-ui-vaadin-widgetset/src/main/resources/VAADIN/themes/admincentraltheme/shell.scss @@ -3,13 +3,13 @@ @mixin shell { .v-viewport-shellapps { - -webkit-backface-visibility: hidden; - -webkit-transform: translateZ(0); + //-webkit-backface-visibility: hidden; + //-webkit-transform: translateZ(0); } .v-table-body { - -webkit-backface-visibility: hidden; - -webkit-transform: translateZ(0); + //-webkit-backface-visibility: hidden; + //-webkit-transform: translateZ(0); } .v-view { diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/AbstractContentPresenter.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/AbstractContentPresenter.java index b390d4e..6b2da24 100644 --- a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/AbstractContentPresenter.java +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/AbstractContentPresenter.java @@ -34,7 +34,6 @@ package info.magnolia.ui.workbench; import info.magnolia.context.MgnlContext; -import info.magnolia.event.EventBus; import info.magnolia.jcr.util.NodeTypes; import info.magnolia.jcr.util.NodeUtil; import info.magnolia.objectfactory.ComponentProvider; @@ -43,24 +42,11 @@ import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter; import info.magnolia.ui.vaadin.integration.jcr.JcrItemUtil; import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter; import info.magnolia.ui.vaadin.integration.jcr.JcrPropertyAdapter; -import info.magnolia.ui.workbench.column.definition.ColumnDefinition; -import info.magnolia.ui.workbench.definition.ContentPresenterDefinition; import info.magnolia.ui.workbench.definition.NodeTypeDefinition; -import info.magnolia.ui.workbench.definition.WorkbenchDefinition; -import info.magnolia.ui.workbench.event.ItemDoubleClickedEvent; -import info.magnolia.ui.workbench.event.ItemRightClickedEvent; -import info.magnolia.ui.workbench.event.ItemShortcutKeyEvent; -import info.magnolia.ui.workbench.event.SelectionChangedEvent; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; import javax.inject.Inject; import javax.jcr.Node; -import javax.jcr.Property; import javax.jcr.RepositoryException; import org.slf4j.Logger; @@ -71,180 +57,32 @@ import com.vaadin.data.Item; /** * Abstract generic logic for content presenters. */ -public abstract class AbstractContentPresenter implements ContentPresenter, ContentView.Listener { +public abstract class AbstractContentPresenter extends AbstractContentPresenterBase { - private static final Logger log = LoggerFactory.getLogger(AbstractContentPresenter.class); - - private static final String ICON_PROPERTY = "icon-node-data"; - - private static final String ICON_TRASH = "icon-trash"; - - protected EventBus eventBus; - - protected WorkbenchDefinition workbenchDefinition; - - private List selectedItemIds = new ArrayList(); - - protected String viewTypeName; - - private final ComponentProvider componentProvider; + private static final Logger log = LoggerFactory.getLogger(AbstractContentPresenterBase.class); @Inject public AbstractContentPresenter(ComponentProvider componentProvider) { - this.componentProvider = componentProvider; - } - - protected ComponentProvider getComponentProvider() { - return componentProvider; - } - - @Override - public ContentView start(WorkbenchDefinition workbenchDefinition, EventBus eventBus, String viewTypeName) { - this.workbenchDefinition = workbenchDefinition; - this.eventBus = eventBus; - this.viewTypeName = viewTypeName; - return null; - } - - @Override - public List getSelectedItemIds() { - return this.selectedItemIds; - } - - public String getSelectedItemId() { - return selectedItemIds.isEmpty() ? null : selectedItemIds.get(0); + super(componentProvider); } @Override - public void setSelectedItemIds(List selectedItemIds) { - this.selectedItemIds = selectedItemIds; - } - - // CONTENT VIEW LISTENER - - @Override - public void onItemSelection(Set items) { + protected String resolveWorkbenchRootId() { try { - Set jcrItems = new LinkedHashSet(); - if (items == null || items.isEmpty()) { - log.debug("Got null com.vaadin.data.Item. ItemSelectedEvent will be fired with null path."); - List ids = new ArrayList(1); - ids.add(JcrItemUtil.getItemId(getWorkbenchRoot())); - setSelectedItemIds(ids); - jcrItems.add(toJcrItemAdapter(getWorkbenchRoot())); - } else { - List itemIds = new ArrayList(items.size()); - for (String item : items) { - // if the selection is done by clicking the checkbox, the root item is added to the set - so it has to be ignored - // but only if there is any other item in the set - // TODO MGNLUI-1521 - if (JcrItemUtil.getItemId(getWorkbenchRoot()).equals(item) && items.size() > 1) { - continue; - } - itemIds.add(item); - jcrItems.add(toJcrItemAdapter(JcrItemUtil.getJcrItem(workbenchDefinition.getWorkspace(), item))); - } - setSelectedItemIds(itemIds); - log.debug("com.vaadin.data.Item at {} was selected. Firing ItemSelectedEvent...", itemIds.toArray()); - } - eventBus.fireEvent(new SelectionChangedEvent(workbenchDefinition.getWorkspace(), jcrItems)); - } catch (Exception e) { - log.error("An error occurred while selecting a row in the data grid", e); - } - } - - private Node getWorkbenchRoot() { - try { - return MgnlContext.getJCRSession(workbenchDefinition.getWorkspace()).getNode(workbenchDefinition.getPath()); + return JcrItemUtil.getItemId(getWorkbenchRoot()); } catch (RepositoryException e) { - log.debug("Cannot find workbench root node for workspace=[" + workbenchDefinition.getWorkspace() + "] and path=[" + workbenchDefinition.getPath() + "]. Error: " + e.getMessage()); - return null; - } - } - - private JcrItemAdapter toJcrItemAdapter(javax.jcr.Item item) { - if (item == null) { + log.error("Failed to resolve workbench root id", e); return null; } - JcrItemAdapter adapter = null; - if (item.isNode()) { - adapter = new JcrNodeAdapter((Node) item); - } else { - adapter = new JcrPropertyAdapter((Property) item); - } - return adapter; } @Override - public void onDoubleClick(Item item) { - if (item != null) { - try { - List ids = new ArrayList(1); - ids.add(((JcrItemAdapter) item).getItemId()); - setSelectedItemIds(ids); - log.debug("com.vaadin.data.Item at {} was double clicked. Firing ItemDoubleClickedEvent...", getSelectedItemId()); - eventBus.fireEvent(new ItemDoubleClickedEvent(workbenchDefinition.getWorkspace(), getSelectedItemId())); - } catch (Exception e) { - log.error("An error occurred while double clicking on a row in the data grid", e); - } - } else { - log.warn("Got null com.vaadin.data.Item. No event will be fired."); - } - } - - @Override - public void onRightClick(Item item, int clickX, int clickY) { - if (item != null) { - try { - // if the right-clicket item is not yet selected - if (!selectedItemIds.contains(((JcrItemAdapter) item).getItemId())) { - List ids = new ArrayList(1); - ids.add(((JcrItemAdapter) item).getItemId()); - setSelectedItemIds(ids); - select(ids); - } - String clickedItemId = ((JcrItemAdapter) item).getItemId(); - log.debug("com.vaadin.data.Item at {} was right clicked. Firing ItemRightClickedEvent...", clickedItemId); - eventBus.fireEvent(new ItemRightClickedEvent(workbenchDefinition.getWorkspace(), (JcrItemAdapter) item, clickX, clickY)); - } catch (Exception e) { - log.error("An error occurred while right clicking on a row in the data grid", e); - } - } else { - log.warn("Got null com.vaadin.data.Item. No event will be fired."); - } - } - - @Override - public void onShortcutKey(int keyCode, int[] modifierKeys) { - JcrItemAdapter item; - - if (selectedItemIds.size() == 1) { - try { - item = toJcrItemAdapter(JcrItemUtil.getJcrItem(workbenchDefinition.getWorkspace(), getSelectedItemId())); - // item = getSelectedItemId(); - log.debug("com.vaadin.data.Item at {} was keyboard clicked. Firing ItemShortcutKeyEvent...", getSelectedItemId()); - eventBus.fireEvent(new ItemShortcutKeyEvent(workbenchDefinition.getWorkspace(), item, keyCode, modifierKeys)); - } catch (Exception e) { - log.error("An error occurred while a key was pressed with a selected row in the data grid", e); - } - } else { - log.warn("Got null com.vaadin.data.Item. No event will be fired."); - } - } - - protected Iterator getColumnsIterator() { - Iterator viewsIterator = workbenchDefinition.getContentViews().iterator(); - while (viewsIterator.hasNext()) { - ContentPresenterDefinition contentView = viewsIterator.next(); - if (contentView.getViewType().equals(viewTypeName)) { - return getAvailableColumns(contentView.getColumns()).iterator(); - } - } - return null; + protected String getItemId(Item item) { + return ((JcrItemAdapter) item).getItemId(); } @Override - public String getIcon(Item item) { + public String getIcon(Item item) { try { if (item instanceof JcrPropertyAdapter) { return ICON_PROPERTY; @@ -280,23 +118,17 @@ public abstract class AbstractContentPresenter implements ContentPresenter, Cont return null; } - protected List getAvailableColumns(final List allColumns) { - final List availableColumns = new ArrayList(); - Iterator it = allColumns.iterator(); - while (it.hasNext()) { - ColumnDefinition column = it.next(); - if (column.isEnabled() && (column.getRuleClass() == null || componentProvider.newInstance(column.getRuleClass(), column).isAvailable())) { - availableColumns.add(column); - } - } - return availableColumns; - } - @Override - public void select(List itemIds) { + public void refresh() { + } - @Override - public void expand(String itemId) { + private Node getWorkbenchRoot() { + try { + return MgnlContext.getJCRSession(workbenchDefinition.getWorkspace()).getNode(workbenchDefinition.getPath()); + } catch (RepositoryException e) { + log.debug("Cannot find workbench root node for workspace=[" + workbenchDefinition.getWorkspace() + "] and path=[" + workbenchDefinition.getPath() + "]. Error: " + e.getMessage()); + return null; + } } } diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/AbstractContentPresenterBase.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/AbstractContentPresenterBase.java new file mode 100644 index 0000000..ddbf3f8 --- /dev/null +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/AbstractContentPresenterBase.java @@ -0,0 +1,249 @@ +/** + * This file Copyright (c) 2013 Magnolia International + * Ltd. (http://www.magnolia-cms.com). All rights reserved. + * + * + * This file is dual-licensed under both the Magnolia + * Network Agreement and the GNU General Public License. + * You may elect to use one or the other of these licenses. + * + * This file is distributed in the hope that it will be + * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. + * Redistribution, except as permitted by whichever of the GPL + * or MNA you select, is prohibited. + * + * 1. For the GPL license (GPL), you can redistribute and/or + * modify this file under the terms of the GNU General + * Public License, Version 3, as published by the Free Software + * Foundation. You should have received a copy of the GNU + * General Public License, Version 3 along with this program; + * if not, write to the Free Software Foundation, Inc., 51 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 2. For the Magnolia Network Agreement (MNA), this file + * and the accompanying materials are made available under the + * terms of the MNA which accompanies this distribution, and + * is available at http://www.magnolia-cms.com/mna.html + * + * Any modifications to this file must keep this entire header + * intact. + * + */ +package info.magnolia.ui.workbench; + +import info.magnolia.event.EventBus; +import info.magnolia.objectfactory.ComponentProvider; +import info.magnolia.ui.workbench.column.definition.ColumnDefinition; +import info.magnolia.ui.workbench.definition.ContentPresenterDefinition; +import info.magnolia.ui.workbench.definition.WorkbenchDefinition; +import info.magnolia.ui.workbench.event.ItemDoubleClickedEvent; +import info.magnolia.ui.workbench.event.ItemRightClickedEvent; +import info.magnolia.ui.workbench.event.ItemShortcutKeyEvent; +import info.magnolia.ui.workbench.event.SelectionChangedEvent; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.vaadin.data.Container; +import com.vaadin.data.Item; + +/** + * Created with IntelliJ IDEA. + * User: sasha + * Date: 04/02/14 + * Time: 16:05 + * To change this template use File | Settings | File Templates. + */ +public abstract class AbstractContentPresenterBase implements ContentPresenter, ContentView.Listener { + + private static final Logger log = LoggerFactory.getLogger(AbstractContentPresenter.class); + + protected static final String ICON_PROPERTY = "icon-node-data"; + + protected static final String ICON_TRASH = "icon-trash"; + + protected EventBus eventBus; + + protected WorkbenchDefinition workbenchDefinition; + + private List selectedItemIds = new ArrayList(); + + protected String viewTypeName; + + private final ComponentProvider componentProvider; + + public AbstractContentPresenterBase(ComponentProvider componentProvider) { + this.componentProvider = componentProvider; + } + + protected ComponentProvider getComponentProvider() { + return componentProvider; + } + + @Override + public ContentView start(WorkbenchDefinition workbenchDefinition, EventBus eventBus, String viewTypeName) { + this.workbenchDefinition = workbenchDefinition; + this.eventBus = eventBus; + this.viewTypeName = viewTypeName; + return null; + } + + @Override + public List getSelectedItemIds() { + return this.selectedItemIds; + } + + public IDTYPE getSelectedItemId() { + return selectedItemIds.isEmpty() ? null : selectedItemIds.get(0); + } + + @Override + public void setSelectedItemIds(List selectedItemIds) { + this.selectedItemIds = selectedItemIds; + } + + // CONTENT VIEW LISTENER + + @Override + public void onItemSelection(Set itemIds) { + IDTYPE rootItemId = resolveWorkbenchRootId(); + if (itemIds == null || itemIds.isEmpty()) { + log.debug("Got null com.vaadin.data.Item. ItemSelectedEvent will be fired with null path."); + List ids = new ArrayList(1); + + ids.add(rootItemId); + setSelectedItemIds(ids); + } else { + Iterator itemIdIt = itemIds.iterator(); + while (itemIdIt.hasNext()) { + IDTYPE item = (IDTYPE) itemIdIt.next(); + // if the selection is done by clicking the checkbox, the root item is added to the set - so it has to be ignored + // but only if there is any other item in the set + // TODO MGNLUI-1521 + try { + if (rootItemId.equals(item) && itemIds.size() > 1) { + itemIdIt.remove(); + } + } catch (Exception e) { + log.error("An error occurred while selecting a row in the data grid", e); + } + } + + List selectedIds = new ArrayList(itemIds.size()); + for (Object id : itemIds) { + selectedIds.add((IDTYPE) id); + } + + setSelectedItemIds(new ArrayList(selectedIds)); + log.debug("com.vaadin.data.Item at {} was selected. Firing ItemSelectedEvent...", itemIds.toArray()); + } + eventBus.fireEvent(new SelectionChangedEvent(itemIds)); + + } + + protected abstract IDTYPE resolveWorkbenchRootId(); + + @Override + public void onDoubleClick(Object itemId) { + if (itemId != null) { + try { + List ids = new ArrayList(1); + ids.add((IDTYPE) itemId); + setSelectedItemIds(ids); + log.debug("com.vaadin.data.Item at {} was double clicked. Firing ItemDoubleClickedEvent...", getSelectedItemId()); + eventBus.fireEvent(new ItemDoubleClickedEvent(getSelectedItemId())); + } catch (Exception e) { + log.error("An error occurred while double clicking on a row in the data grid", e); + } + } else { + log.warn("Got null com.vaadin.data.Item. No event will be fired."); + } + } + + protected abstract String getItemId(Item item); + + @Override + public void onRightClick(Object itemId, int clickX, int clickY) { + if (itemId != null) { + try { + // if the right-clicket item is not yet selected + if (!selectedItemIds.contains(itemId)) { + List ids = new ArrayList(1); + ids.add((IDTYPE) itemId); + setSelectedItemIds(ids); + select(ids); + } + log.debug("com.vaadin.data.Item at {} was right clicked. Firing ItemRightClickedEvent...", itemId); + //TODO JCRFREE Here we'd better use some id instead of path, but so far should be okay + //eventBus.fireEvent(new ItemRightClickedEvent(((JcrNodeAdapter) item).getJcrItem().getId(), clickX, clickY)); + eventBus.fireEvent(new ItemRightClickedEvent(itemId, clickX, clickY)); + } catch (Exception e) { + log.error("An error occurred while right clicking on a row in the data grid", e); + } + } else { + log.warn("Got null com.vaadin.data.Item. No event will be fired."); + } + } + + @Override + public void onShortcutKey(int keyCode, int[] modifierKeys) { + Item item; + + if (selectedItemIds.size() == 1) { + try { + item = getContainer().getItem(getSelectedItemId()); + // item = getSelectedItemId(); + log.debug("com.vaadin.data.Item at {} was keyboard clicked. Firing ItemShortcutKeyEvent...", getSelectedItemId()); + eventBus.fireEvent(new ItemShortcutKeyEvent(item, keyCode, modifierKeys)); + } catch (Exception e) { + log.error("An error occurred while a key was pressed with a selected row in the data grid", e); + } + } else { + log.warn("Got null com.vaadin.data.Item. No event will be fired."); + } + } + + protected Iterator getColumnsIterator() { + Iterator viewsIterator = workbenchDefinition.getContentViews().iterator(); + while (viewsIterator.hasNext()) { + ContentPresenterDefinition contentView = viewsIterator.next(); + String viewType = contentView.getViewType(); + if (viewType != null && viewType.equals(viewTypeName)) { + return getAvailableColumns(contentView.getColumns()).iterator(); + } + } + return null; + } + + @Override + public abstract String getIcon(Item item); + + + protected List getAvailableColumns(final List allColumns) { + final List availableColumns = new ArrayList(); + Iterator it = allColumns.iterator(); + while (it.hasNext()) { + ColumnDefinition column = it.next(); + if (column.isEnabled() && (column.getRuleClass() == null || componentProvider.newInstance(column.getRuleClass(), column).isAvailable())) { + availableColumns.add(column); + } + } + return availableColumns; + } + + @Override + public void select(List itemIds) {} + + @Override + public void expand(String itemId) {} + + protected abstract Container getContainer(); +} \ No newline at end of file diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/ContentPresenter.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/ContentPresenter.java index 726b823..3326299 100644 --- a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/ContentPresenter.java +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/ContentPresenter.java @@ -48,7 +48,7 @@ import java.util.List; * Content presenters are configured using the implentationClass property of a {@link info.magnolia.ui.workbench.definition.ContentPresenterDefinition}, * and by registering such definition in the workbench's contentViews node in configuration. */ -public interface ContentPresenter { +public interface ContentPresenter { /** * Initializes the presenter with the workbench definition, eventBus and viewType name. @@ -68,17 +68,17 @@ public interface ContentPresenter { /** * @return the selected item ids in the content view. */ - List getSelectedItemIds(); + List getSelectedItemIds(); /** * Sets the selected item ids for this presenter to react on, e.g. with keyboard shortcuts. */ - void setSelectedItemIds(List itemId); + void setSelectedItemIds(List itemId); /** * Selects the given items in the content view. */ - void select(List itemIds); + void select(List itemIds); /** * Make sure the given items are visible in the content view. diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/ContentView.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/ContentView.java index ab356fd..45627d5 100644 --- a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/ContentView.java +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/ContentView.java @@ -49,17 +49,17 @@ public interface ContentView extends View { /** * Selects the items with given IDs in the content view. - * + * * @param itemIds IDs */ - void select(List itemIds); + void select(List itemIds); /** * Expands an item if the view supports it. - * + * * @param itemId ID */ - void expand(String itemId); + void expand(Object itemId); void onShortcutKey(int keyCode, int[] modifierKeys); @@ -73,11 +73,11 @@ public interface ContentView extends View { */ public interface Listener { - void onItemSelection(Set items); + void onItemSelection(Set items); - void onDoubleClick(Item item); + void onDoubleClick(Object itemId); - void onRightClick(Item item, int clickX, int clickY); + void onRightClick(Object itemId, int clickX, int clickY); void onShortcutKey(int keyCode, int... modifierKeys); diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/WorkbenchPresenter.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/WorkbenchPresenter.java index d0de56b..142d942 100644 --- a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/WorkbenchPresenter.java +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/WorkbenchPresenter.java @@ -33,281 +33,89 @@ */ package info.magnolia.ui.workbench; -import info.magnolia.event.EventBus; import info.magnolia.objectfactory.ComponentProvider; -import info.magnolia.ui.imageprovider.ImageProvider; -import info.magnolia.ui.imageprovider.definition.ImageProviderDefinition; import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter; import info.magnolia.ui.vaadin.integration.jcr.JcrItemUtil; import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter; import info.magnolia.ui.vaadin.integration.jcr.JcrPropertyAdapter; -import info.magnolia.ui.workbench.definition.ContentPresenterDefinition; import info.magnolia.ui.workbench.definition.WorkbenchDefinition; -import info.magnolia.ui.workbench.event.SearchEvent; -import info.magnolia.ui.workbench.event.SelectionChangedEvent; -import info.magnolia.ui.workbench.event.ViewTypeChangedEvent; -import info.magnolia.ui.workbench.list.ListPresenterDefinition; -import info.magnolia.ui.workbench.search.SearchPresenter; -import info.magnolia.ui.workbench.search.SearchPresenterDefinition; -import info.magnolia.ui.workbench.tree.TreePresenter; +import info.magnolia.ui.workbench.tree.HierarchicalJcrContainer; import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; -import java.util.Set; import javax.inject.Inject; -import javax.jcr.Item; import javax.jcr.Node; import javax.jcr.Property; import javax.jcr.RepositoryException; -import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.vaadin.data.Container; +import com.vaadin.data.Item; + /** * The WorkbenchPresenter is responsible for creating, configuring and updating the workbench view, as well as handling its interaction. */ -public class WorkbenchPresenter implements WorkbenchView.Listener { - - private static final Logger log = LoggerFactory.getLogger(WorkbenchPresenter.class); - - private final WorkbenchView view; - - private final ComponentProvider componentProvider; - - private final Map contentPresenters = new LinkedHashMap(); +public class WorkbenchPresenter extends WorkbenchPresenterBase { - private ContentPresenter activePresenter; - - private final WorkbenchStatusBarPresenter statusBarPresenter; - - private WorkbenchDefinition workbenchDefinition; - - private EventBus eventBus; + private Logger log = LoggerFactory.getLogger(getClass()); @Inject public WorkbenchPresenter(WorkbenchView view, ComponentProvider componentProvider, WorkbenchStatusBarPresenter statusBarPresenter) { - this.view = view; - this.componentProvider = componentProvider; - this.statusBarPresenter = statusBarPresenter; + super(view, componentProvider, statusBarPresenter); } - public WorkbenchView start(WorkbenchDefinition workbenchDefinition, ImageProviderDefinition imageProviderDefinition, EventBus eventBus) { - this.workbenchDefinition = workbenchDefinition; - this.eventBus = eventBus; - - sanityCheck(workbenchDefinition); - - // add content views - for (final ContentPresenterDefinition presenterDefinition : workbenchDefinition.getContentViews()) { - ContentPresenter presenter = null; - Class presenterClass = presenterDefinition.getImplementationClass(); - if (presenterClass != null) { - presenter = newPresenterInstance(componentProvider, imageProviderDefinition, presenterClass); - contentPresenters.put(presenterDefinition.getViewType(), presenter); - ContentView contentView = presenter.start(workbenchDefinition, eventBus, presenterDefinition.getViewType()); - - if (presenterDefinition.isActive()) { - activePresenter = presenter; - List ids = new ArrayList(1); - if (workbenchDefinition.getWorkspace() != null) { - try { - String workbenchRootItemId = JcrItemUtil.getItemId(workbenchDefinition.getWorkspace(), workbenchDefinition.getPath()); - ids.add(workbenchRootItemId); - activePresenter.setSelectedItemIds(ids); - } catch (RepositoryException e) { - log.error("Could not find workbench root node", e); - } - } - } - view.addContentView(presenterDefinition.getViewType(), contentView, presenterDefinition); - - if (presenter instanceof TreePresenter && workbenchDefinition.isDialogWorkbench()) { - ((TreePresenter) presenter).disableDragAndDrop(); - } - } else { - throw new RuntimeException("The provided view type [" + presenterDefinition.getViewType() + "] is not valid."); - } - - } - - // add status bar - view.setStatusBarView(statusBarPresenter.start(eventBus, workbenchDefinition)); - - view.setListener(this); - return view; - } - - protected void sanityCheck(WorkbenchDefinition workbenchDefinition) { - if (workbenchDefinition == null) { - throw new IllegalArgumentException("Trying to init a workbench but got null definition."); - } - - if (StringUtils.isBlank(workbenchDefinition.getWorkspace())) { - throw new IllegalStateException(workbenchDefinition.getName() + " workbench definition must specify a workspace to connect to. Please, check your configuration."); - } - } - - protected ContentPresenter newPresenterInstance(ComponentProvider componentProvider, ImageProviderDefinition imageProviderDefinition, Class presenterClass) { - ContentPresenter presenter; - if (imageProviderDefinition != null) { - ImageProvider imageProvider = componentProvider.newInstance(imageProviderDefinition.getImageProviderClass(), imageProviderDefinition); - presenter = componentProvider.newInstance(presenterClass, imageProvider); - } else { - presenter = componentProvider.newInstance(presenterClass); + @Override + public String resolveWorkbenchRoot() { + try { + return JcrItemUtil.getItemId(getWorkbenchDefinition().getWorkspace(), getWorkbenchDefinition().getPath()); + } catch (RepositoryException e) { + log.error("Could not find workbench root node", e); + return null; } - return presenter; } @Override - public void onSearch(final String searchExpression) { - if (hasViewType(SearchPresenterDefinition.VIEW_TYPE)) { - if (StringUtils.isNotBlank(searchExpression)) { - eventBus.fireEvent(new SearchEvent(searchExpression)); + public Item getItemFor(String itemId) { + javax.jcr.Item jcrItem; + try { + jcrItem = JcrItemUtil.getJcrItem(getWorkspace(), itemId); + JcrItemAdapter itemAdapter; + if (jcrItem.isNode()) { + itemAdapter = new JcrNodeAdapter((Node) jcrItem); } else { - // if search expression is empty switch to list view - onViewTypeChanged(ListPresenterDefinition.VIEW_TYPE); + itemAdapter = new JcrPropertyAdapter((Property) jcrItem); } - } else { - log.warn("Workbench view triggered search although the search view type is not configured in this workbench {}", this); + return itemAdapter; + } catch (RepositoryException e) { + log.error("Failed to find item for id", e); + return null; } } @Override - public void onViewTypeChanged(final String viewType) { - setViewType(viewType); - eventBus.fireEvent(new ViewTypeChangedEvent(viewType)); - } - - private void setViewType(String viewType) { - ContentPresenter oldPresenter = activePresenter; - List itemIds = oldPresenter == null ? null : oldPresenter.getSelectedItemIds(); - - activePresenter = contentPresenters.get(viewType); - activePresenter.refresh(); - view.setViewType(viewType); - - // make sure selection is kept when switching views - if (itemIds != null) { - select(itemIds); - } - } - - public String getWorkspace() { - return workbenchDefinition.getWorkspace(); - } - - public List getSelectedIds() { - return activePresenter.getSelectedItemIds(); - } - - public void expand(String itemId) { - activePresenter.expand(itemId); - } - - public void select(String itemId) { - List ids = new ArrayList(1); - ids.add(itemId); - select(ids); - } - - public void select(List itemIds) { - try { - // restore selection - Set items = new LinkedHashSet(); - List selectedIds = new ArrayList(); - boolean rootHasBeenSelected = false; - for (String itemId : itemIds) { + protected List filterExistingItems(List itemIds) { + List filteredIds = new ArrayList(); + for (String itemId : itemIds) { + try { if (JcrItemUtil.itemExists(getWorkspace(), itemId)) { - selectedIds.add(itemId); - - Item jcrItem = JcrItemUtil.getJcrItem(getWorkspace(), itemId); - JcrItemAdapter itemAdapter; - if (jcrItem.isNode()) { - itemAdapter = new JcrNodeAdapter((Node) jcrItem); - } else { - itemAdapter = new JcrPropertyAdapter((Property) jcrItem); - } - items.add(itemAdapter); - + filteredIds.add(itemId); } else { - log.info("Trying to re-sync workbench with no longer existing path {} at workspace {}. Will reset path to its configured root {}.", - new Object[] { itemId, workbenchDefinition.getWorkspace(), workbenchDefinition.getPath() }); - String workbenchRootItemId = JcrItemUtil.getItemId(workbenchDefinition.getWorkspace(), workbenchDefinition.getPath()); - if (!rootHasBeenSelected && !selectedIds.contains(workbenchRootItemId)) { - // adding workbenchRootItemID for non-existent items, but just once - selectedIds.add(workbenchRootItemId); - rootHasBeenSelected = true; - } + WorkbenchDefinition def = getWorkbenchDefinition(); + log.info("Trying to re-sync workbench with no longer existing path {} at workspace {}. Will reset path to its configured root {}.", new Object[] { itemId, def.getWorkspace(), def.getPath() }); } + } catch (RepositoryException e) { + log.error("Error occurred while filtering existing ids", e); + continue; } - activePresenter.setSelectedItemIds(selectedIds); - activePresenter.select(selectedIds); - // Only send event if items are not empty (do exist) - if (!items.isEmpty()) { - eventBus.fireEvent(new SelectionChangedEvent(workbenchDefinition.getWorkspace(), items)); - } - - } catch (RepositoryException e) { - log.warn("Unable to get node or property [{}] for selection", itemIds, e); } + return filteredIds; } - public void refresh() { - activePresenter.refresh(); - } - - public String getDefaultViewType() { - for (ContentPresenterDefinition definition : this.workbenchDefinition.getContentViews()) { - if (definition.isActive()) { - return definition.getViewType(); - } - } - return this.workbenchDefinition.getContentViews().get(0).getViewType(); - } - - public boolean hasViewType(String viewType) { - return contentPresenters.containsKey(viewType); - } - - public void resynch(final List itemIds, final String viewType, final String query) { - setViewType(viewType); - select(itemIds); - - if (SearchPresenterDefinition.VIEW_TYPE.equals(viewType)) { - doSearch(query); - // update search field and focus it - view.setSearchQuery(query); - } - } - - public void doSearch(String searchExpression) { - // firing new search forces search view as new view type - if (activePresenter != contentPresenters.get(SearchPresenterDefinition.VIEW_TYPE)) { - setViewType(SearchPresenterDefinition.VIEW_TYPE); - } - final SearchPresenter searchPresenter = (SearchPresenter) activePresenter; - if (StringUtils.isBlank(searchExpression)) { - searchPresenter.clear(); - } else { - searchPresenter.search(searchExpression); - } - } - - // exposed only for extending classes. these methods should not be public! - protected final ContentPresenter getActivePresenter() { - return activePresenter; - } - - protected final EventBus getEventBus() { - return this.eventBus; - } - - protected final WorkbenchDefinition getWorkspaceDefinition() { - return this.workbenchDefinition; + @Override + protected Container getContainer() { + return new HierarchicalJcrContainer(getWorkbenchDefinition()); } } \ No newline at end of file diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/WorkbenchPresenterBase.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/WorkbenchPresenterBase.java new file mode 100644 index 0000000..7307f6b --- /dev/null +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/WorkbenchPresenterBase.java @@ -0,0 +1,298 @@ +/** + * This file Copyright (c) 2013 Magnolia International + * Ltd. (http://www.magnolia-cms.com). All rights reserved. + * + * + * This file is dual-licensed under both the Magnolia + * Network Agreement and the GNU General Public License. + * You may elect to use one or the other of these licenses. + * + * This file is distributed in the hope that it will be + * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. + * Redistribution, except as permitted by whichever of the GPL + * or MNA you select, is prohibited. + * + * 1. For the GPL license (GPL), you can redistribute and/or + * modify this file under the terms of the GNU General + * Public License, Version 3, as published by the Free Software + * Foundation. You should have received a copy of the GNU + * General Public License, Version 3 along with this program; + * if not, write to the Free Software Foundation, Inc., 51 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 2. For the Magnolia Network Agreement (MNA), this file + * and the accompanying materials are made available under the + * terms of the MNA which accompanies this distribution, and + * is available at http://www.magnolia-cms.com/mna.html + * + * Any modifications to this file must keep this entire header + * intact. + * + */ +package info.magnolia.ui.workbench; + +import info.magnolia.event.EventBus; +import info.magnolia.objectfactory.ComponentProvider; +import info.magnolia.ui.imageprovider.ImageProvider; +import info.magnolia.ui.imageprovider.definition.ImageProviderDefinition; +import info.magnolia.ui.workbench.definition.ContentPresenterDefinition; +import info.magnolia.ui.workbench.definition.WorkbenchDefinition; +import info.magnolia.ui.workbench.event.SearchEvent; +import info.magnolia.ui.workbench.event.SelectionChangedEvent; +import info.magnolia.ui.workbench.event.ViewTypeChangedEvent; +import info.magnolia.ui.workbench.list.ListPresenterDefinition; +import info.magnolia.ui.workbench.search.SearchPresenter; +import info.magnolia.ui.workbench.search.SearchPresenterDefinition; +import info.magnolia.ui.workbench.tree.TreePresenter; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + + +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.vaadin.data.Container; +import com.vaadin.data.Item; + +/** + * Created with IntelliJ IDEA. + * User: sasha + * Date: 04/02/14 + * Time: 10:57 + * To change this template use File | Settings | File Templates. + */ +public abstract class WorkbenchPresenterBase implements WorkbenchView.Listener { + + private static final Logger log = LoggerFactory.getLogger(WorkbenchPresenter.class); + + private final WorkbenchView view; + + private final ComponentProvider componentProvider; + + private final Map contentPresenters = new LinkedHashMap(); + + private ContentPresenter activePresenter; + + private final WorkbenchStatusBarPresenter statusBarPresenter; + + private WorkbenchDefinition workbenchDefinition; + + private EventBus eventBus; + + public WorkbenchPresenterBase(WorkbenchView view, ComponentProvider componentProvider, WorkbenchStatusBarPresenter statusBarPresenter) { + this.view = view; + this.componentProvider = componentProvider; + this.statusBarPresenter = statusBarPresenter; + } + + public WorkbenchView start(WorkbenchDefinition workbenchDefinition, ImageProviderDefinition imageProviderDefinition, EventBus eventBus) { + this.workbenchDefinition = workbenchDefinition; + this.eventBus = eventBus; + + sanityCheck(workbenchDefinition); + + // add content views + for (final ContentPresenterDefinition presenterDefinition : workbenchDefinition.getContentViews()) { + ContentPresenter presenter = null; + Class presenterClass = presenterDefinition.getImplementationClass(); + if (presenterClass != null) { + presenter = newPresenterInstance(componentProvider, imageProviderDefinition, presenterClass); + contentPresenters.put(presenterDefinition.getViewType(), presenter); + ContentView contentView = presenter.start(workbenchDefinition, eventBus, presenterDefinition.getViewType()); + + if (presenterDefinition.isActive()) { + activePresenter = presenter; + List ids = new ArrayList(1); + if (workbenchDefinition.getWorkspace() != null) { + IDTYPE workbenchRootItemId = resolveWorkbenchRoot(); + ids.add(workbenchRootItemId); + activePresenter.setSelectedItemIds(ids); + } + } + view.addContentView(presenterDefinition.getViewType(), contentView, presenterDefinition); + + if (presenter instanceof TreePresenter && workbenchDefinition.isDialogWorkbench()) { + ((TreePresenter) presenter).disableDragAndDrop(); + } + } else { + throw new RuntimeException("The provided view type [" + presenterDefinition.getViewType() + "] is not valid."); + } + + } + + // add status bar + view.setStatusBarView(statusBarPresenter.start(eventBus, workbenchDefinition)); + + view.setListener(this); + return view; + } + + public abstract IDTYPE resolveWorkbenchRoot(); + + protected void sanityCheck(WorkbenchDefinition workbenchDefinition) { + if (workbenchDefinition == null) { + throw new IllegalArgumentException("Trying to init a workbench but got null definition."); + } + + if (StringUtils.isBlank(workbenchDefinition.getWorkspace())) { + throw new IllegalStateException(workbenchDefinition.getName() + " workbench definition must specify a workspace to connect to. Please, check your configuration."); + } + } + + protected ContentPresenter newPresenterInstance(ComponentProvider componentProvider, ImageProviderDefinition imageProviderDefinition, Class presenterClass) { + ContentPresenter presenter; + + List args = new ArrayList(); + args.add(componentProvider); + if (imageProviderDefinition != null) { + ImageProvider imageProvider = componentProvider.newInstance(imageProviderDefinition.getImageProviderClass(), imageProviderDefinition); + args.add(imageProvider); + } + + Container c = getContainer(); + if (c != null) { + args.add(c); + } + presenter = componentProvider.newInstance(presenterClass, args.toArray(new Object[args.size()])); + return presenter; + } + + @Override + public void onSearch(final String searchExpression) { + if (hasViewType(SearchPresenterDefinition.VIEW_TYPE)) { + if (StringUtils.isNotBlank(searchExpression)) { + eventBus.fireEvent(new SearchEvent(searchExpression)); + } else { + // if search expression is empty switch to list view + onViewTypeChanged(ListPresenterDefinition.VIEW_TYPE); + } + } else { + log.warn("Workbench view triggered search although the search view type is not configured in this workbench {}", this); + } + } + + @Override + public void onViewTypeChanged(final String viewType) { + setViewType(viewType); + eventBus.fireEvent(new ViewTypeChangedEvent(viewType)); + } + + private void setViewType(String viewType) { + ContentPresenter oldPresenter = activePresenter; + List itemIds = oldPresenter == null ? null : oldPresenter.getSelectedItemIds(); + + activePresenter = contentPresenters.get(viewType); + activePresenter.refresh(); + view.setViewType(viewType); + + // make sure selection is kept when switching views + if (itemIds != null) { + select(itemIds); + } + } + + public String getWorkspace() { + return workbenchDefinition.getWorkspace(); + } + + public List getSelectedIds() { + return activePresenter.getSelectedItemIds(); + } + + public void expand(String itemId) { + activePresenter.expand(itemId); + } + + public void select(IDTYPE itemId) { + List ids = new ArrayList(1); + ids.add(itemId); + select(ids); + } + + public void select(List itemIds) { + final List selectedIds = filterExistingItems(itemIds); + // restore selection + Set items = new LinkedHashSet(); + if (selectedIds.isEmpty()) { + IDTYPE workbenchRootItemId = resolveWorkbenchRoot(); + selectedIds.add(workbenchRootItemId); + } + + activePresenter.setSelectedItemIds(selectedIds); + activePresenter.select(selectedIds); + // Only send event if items are not empty (do exist) + eventBus.fireEvent(new SelectionChangedEvent(new HashSet(itemIds))); + } + + public abstract Item getItemFor(IDTYPE itemId); + + protected abstract List filterExistingItems(List itemIds); + + public void refresh() { + activePresenter.refresh(); + } + + public String getDefaultViewType() { + for (ContentPresenterDefinition definition : this.workbenchDefinition.getContentViews()) { + if (definition.isActive()) { + return definition.getViewType(); + } + } + return this.workbenchDefinition.getContentViews().get(0).getViewType(); + } + + public boolean hasViewType(String viewType) { + return contentPresenters.containsKey(viewType); + } + + public void resynch(final List itemIds, final String viewType, final String query) { + setViewType(viewType); + select(itemIds); + + if (SearchPresenterDefinition.VIEW_TYPE.equals(viewType)) { + doSearch(query); + // update search field and focus it + view.setSearchQuery(query); + } + } + + public void doSearch(String searchExpression) { + // firing new search forces search view as new view type + if (activePresenter != contentPresenters.get(SearchPresenterDefinition.VIEW_TYPE)) { + setViewType(SearchPresenterDefinition.VIEW_TYPE); + } + final SearchPresenter searchPresenter = (SearchPresenter) activePresenter; + if (StringUtils.isBlank(searchExpression)) { + searchPresenter.clear(); + } else { + searchPresenter.search(searchExpression); + } + } + + // exposed only for extending classes. these methods should not be public! + protected final ContentPresenter getActivePresenter() { + return activePresenter; + } + + protected final EventBus getEventBus() { + return this.eventBus; + } + + protected final WorkbenchDefinition getWorkbenchDefinition() { + return this.workbenchDefinition; + } + + protected Container getContainer() { + return null; + } + +} diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/WorkbenchStatusBarPresenter.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/WorkbenchStatusBarPresenter.java index f863109..3ed7ffc 100644 --- a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/WorkbenchStatusBarPresenter.java +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/WorkbenchStatusBarPresenter.java @@ -39,6 +39,7 @@ import info.magnolia.ui.workbench.definition.WorkbenchDefinition; import info.magnolia.ui.workbench.event.SelectionChangedEvent; import java.util.List; +import java.util.Set; import javax.inject.Inject; import javax.jcr.RepositoryException; @@ -47,12 +48,14 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.vaadin.data.Item; import com.vaadin.ui.Alignment; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; /** * The browser features a status bar at the bottom with selected path and item count information. + * TODO JCRFREE - get rid of JcrItemAdapter dependency here. */ public class WorkbenchStatusBarPresenter { @@ -76,7 +79,7 @@ public class WorkbenchStatusBarPresenter { @Override public void onSelectionChanged(SelectionChangedEvent event) { - setSelectedItems(event.getItems()); + setSelectedItems(event.getItemIds()); } }); } @@ -94,9 +97,9 @@ public class WorkbenchStatusBarPresenter { return view; } - public void setSelectedItems(List items) { + public void setSelectedItems(Set items) { if (!items.isEmpty()) { - setSelectedItem(items.get(0)); + //setSelectedItem((JcrItemAdapter) items.get(0)); } } diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/beanworkbench/BeanWorkbenchPresenter.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/beanworkbench/BeanWorkbenchPresenter.java new file mode 100644 index 0000000..d0465a0 --- /dev/null +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/beanworkbench/BeanWorkbenchPresenter.java @@ -0,0 +1,92 @@ +/** + * This file Copyright (c) 2013 Magnolia International + * Ltd. (http://www.magnolia-cms.com). All rights reserved. + * + * + * This file is dual-licensed under both the Magnolia + * Network Agreement and the GNU General Public License. + * You may elect to use one or the other of these licenses. + * + * This file is distributed in the hope that it will be + * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. + * Redistribution, except as permitted by whichever of the GPL + * or MNA you select, is prohibited. + * + * 1. For the GPL license (GPL), you can redistribute and/or + * modify this file under the terms of the GNU General + * Public License, Version 3, as published by the Free Software + * Foundation. You should have received a copy of the GNU + * General Public License, Version 3 along with this program; + * if not, write to the Free Software Foundation, Inc., 51 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 2. For the Magnolia Network Agreement (MNA), this file + * and the accompanying materials are made available under the + * terms of the MNA which accompanies this distribution, and + * is available at http://www.magnolia-cms.com/mna.html + * + * Any modifications to this file must keep this entire header + * intact. + * + */ +package info.magnolia.ui.workbench.beanworkbench; + +import info.magnolia.objectfactory.ComponentProvider; +import info.magnolia.ui.workbench.WorkbenchPresenterBase; +import info.magnolia.ui.workbench.WorkbenchStatusBarPresenter; +import info.magnolia.ui.workbench.WorkbenchView; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import com.vaadin.data.Container; +import com.vaadin.data.Item; +import com.vaadin.data.util.FilesystemContainer; + +/** + * Created with IntelliJ IDEA. + * User: sasha + * Date: 04/02/14 + * Time: 22:36 + * To change this template use File | Settings | File Templates. + */ +public class BeanWorkbenchPresenter extends WorkbenchPresenterBase { + + private FilesystemContainer container = new FilesystemContainer(new File("/Users/sasha/test")); + + @Inject + public BeanWorkbenchPresenter(WorkbenchView view, ComponentProvider componentProvider, WorkbenchStatusBarPresenter statusBarPresenter) { + super(view, componentProvider, statusBarPresenter); + } + + @Override + public Object resolveWorkbenchRoot() { + return new File("/Users/sasha/test"); + } + + @Override + public Item getItemFor(Object itemId) { + return container.getItem(itemId); + } + + @Override + protected List filterExistingItems(List itemIds) { + List result = new ArrayList(); + for (Object id : itemIds) { + if (container.containsId(id)) { + result.add(id); + } + } + return result; + } + + @Override + protected Container getContainer() { + return container; + } +} diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/container/AbstractJcrContainer.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/container/AbstractJcrContainer.java index bae59cd..e81564a 100644 --- a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/container/AbstractJcrContainer.java +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/container/AbstractJcrContainer.java @@ -35,10 +35,10 @@ package info.magnolia.ui.workbench.container; import info.magnolia.context.MgnlContext; import info.magnolia.jcr.util.NodeTypes; -import info.magnolia.ui.api.ModelConstants; import info.magnolia.ui.vaadin.integration.jcr.JcrItemUtil; import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter; import info.magnolia.ui.vaadin.integration.jcr.JcrPropertyAdapter; +import info.magnolia.ui.vaadin.integration.jcr.ModelConstants; import info.magnolia.ui.workbench.definition.NodeTypeDefinition; import info.magnolia.ui.workbench.definition.WorkbenchDefinition; diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/event/ItemDoubleClickedEvent.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/event/ItemDoubleClickedEvent.java index a9f63ab..5cce31b 100644 --- a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/event/ItemDoubleClickedEvent.java +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/event/ItemDoubleClickedEvent.java @@ -50,20 +50,13 @@ public class ItemDoubleClickedEvent implements Event { + public Object getItemId() { + return itemId; + } + /** * Handles {@link ItemRightClickedEvent} events. */ @@ -51,32 +57,18 @@ public class ItemRightClickedEvent implements Event void onItemShortcutKeyEvent(ItemShortcutKeyEvent event); } - private String workspace; - - private final JcrItemAdapter item; + private final Item item; private final int keyCode; private final int[] modifierKeys; - public ItemShortcutKeyEvent(String workspace, JcrItemAdapter item, int keyCode, int... modifierKeys) { - this.workspace = workspace; + public ItemShortcutKeyEvent(Item item, int keyCode, int... modifierKeys) { this.item = item; this.keyCode = keyCode; this.modifierKeys = modifierKeys; } - public String getWorkspace() { - return workspace; - } - - public JcrItemAdapter getItem() { + public Item getItem() { return item; } - public String getItemId() { - return item != null ? item.getItemId() : null; - } - public int getKeyCode() { return keyCode; } diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/event/SelectionChangedEvent.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/event/SelectionChangedEvent.java index 96e2e50..52bf653 100644 --- a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/event/SelectionChangedEvent.java +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/event/SelectionChangedEvent.java @@ -35,15 +35,9 @@ package info.magnolia.ui.workbench.event; import info.magnolia.event.Event; import info.magnolia.event.EventHandler; -import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter; -import info.magnolia.ui.vaadin.integration.jcr.JcrItemUtil; -import java.util.ArrayList; -import java.util.List; import java.util.Set; -import javax.jcr.RepositoryException; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,52 +57,22 @@ public class SelectionChangedEvent implements Event items; - - public SelectionChangedEvent(String workspace, Set items) { - this.workspace = workspace; - List itemList = new ArrayList(items.size()); - for (JcrItemAdapter item : items) { - itemList.add(item); - } - this.items = itemList; - } + private final Set itemsIds; - public String getWorkspace() { - return workspace; + public SelectionChangedEvent(Set itemIds) { + this.itemsIds = itemIds; } - public List getItemIds() { - List itemIds = new ArrayList(items.size()); - for (JcrItemAdapter item : items) { - itemIds.add(item.getItemId()); - } - return itemIds; - } - - public JcrItemAdapter getFirstItem() { - if (items != null && !items.isEmpty()) { - return items.get(0); - } - return null; - } - public String getFirstItemId() { - JcrItemAdapter item = getFirstItem(); - if (item != null) { - try { - return JcrItemUtil.getItemId(item.getJcrItem()); - } catch (RepositoryException e) { - log.debug("Cannot get ID for item [{}]. Error: {}", item, e.getMessage()); - } + public Object getFirstItemId() { + if (itemsIds != null && !itemsIds.isEmpty()) { + return itemsIds.iterator().next(); } return null; } - public List getItems() { - return items; + public Set getItemIds() { + return itemsIds; } @Override diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/list/FSListPresenter.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/list/FSListPresenter.java new file mode 100644 index 0000000..33e3d91 --- /dev/null +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/list/FSListPresenter.java @@ -0,0 +1,152 @@ +/** + * This file Copyright (c) 2013 Magnolia International + * Ltd. (http://www.magnolia-cms.com). All rights reserved. + * + * + * This file is dual-licensed under both the Magnolia + * Network Agreement and the GNU General Public License. + * You may elect to use one or the other of these licenses. + * + * This file is distributed in the hope that it will be + * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. + * Redistribution, except as permitted by whichever of the GPL + * or MNA you select, is prohibited. + * + * 1. For the GPL license (GPL), you can redistribute and/or + * modify this file under the terms of the GNU General + * Public License, Version 3, as published by the Free Software + * Foundation. You should have received a copy of the GNU + * General Public License, Version 3 along with this program; + * if not, write to the Free Software Foundation, Inc., 51 + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 2. For the Magnolia Network Agreement (MNA), this file + * and the accompanying materials are made available under the + * terms of the MNA which accompanies this distribution, and + * is available at http://www.magnolia-cms.com/mna.html + * + * Any modifications to this file must keep this entire header + * intact. + * + */ +package info.magnolia.ui.workbench.list; + +import info.magnolia.event.EventBus; +import info.magnolia.objectfactory.ComponentProvider; +import info.magnolia.ui.workbench.AbstractContentPresenterBase; +import info.magnolia.ui.workbench.column.definition.ColumnDefinition; +import info.magnolia.ui.workbench.container.AbstractJcrContainer; +import info.magnolia.ui.workbench.definition.WorkbenchDefinition; +import info.magnolia.ui.workbench.tree.TreeView; + +import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.inject.Inject; + +import com.vaadin.data.Item; +import com.vaadin.data.util.FilesystemContainer; +import com.vaadin.ui.Table; + +/** + * Created with IntelliJ IDEA. + * User: sasha + * Date: 05/02/14 + * Time: 11:18 + * To change this template use File | Settings | File Templates. + */ +public class FSListPresenter extends AbstractContentPresenterBase implements ListView.Listener { + + + protected final ListView view; + + protected FilesystemContainer container; + + @Inject + public FSListPresenter(final TreeView view, final ComponentProvider componentProvider, FilesystemContainer container) { + super(componentProvider); + this.view = view; + this.container = container; + } + + @Override + public ListView start(WorkbenchDefinition workbench, EventBus eventBus, String viewTypeName) { + super.start(workbench, eventBus, viewTypeName); + + //this.container = createContainer(workbench); + view.setListener(this); + view.setContainer(container); + ((Table)view.asVaadinComponent()).setVisibleColumns(new Object[]{}); + + // build columns + Iterator it = getColumnsIterator(); + + while (it.hasNext()) { + ColumnDefinition column = it.next(); + + String propertyId = column.getPropertyName() != null ? column.getPropertyName() : column.getName(); + String title = column.getLabel(); + //container.addContainerProperty(propertyId, column.getType(), null); + + if (column.getWidth() > 0) { + view.addColumn(propertyId, title, column.getWidth()); + } else if (column.getExpandRatio() > 0) { + view.addColumn(propertyId, title, column.getExpandRatio()); + } else { + view.addColumn(propertyId, column.getLabel()); + } + + if (column.getFormatterClass() != null) { + view.setColumnFormatter(propertyId, getComponentProvider().newInstance(column.getFormatterClass(), column)); + } + + if (column.isSortable()) { + //container.addSortableProperty(propertyId); + } + } + + return view; + } + + @Override + protected File resolveWorkbenchRootId() { + return new File("/Users/sasha/test"); + } + + @Override + protected String getItemId(Item item) { + return null;//getContainer().; + } + + @Override + public String getIcon(Item item) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void select(List itemIds) { + List objectIds = new ArrayList(); + for (Object itemId : itemIds) { + objectIds.add(itemId); + } + view.select(objectIds); + } + + @Override + public void refresh() { + // This will update the row count and display the newly created items. + //container.refresh(); + //container.fireItemSetChange(); + } + + @Override + protected FilesystemContainer getContainer() { + return container; + } + + +} diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/list/ListPresenter.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/list/ListPresenter.java index 3198733..59e3644 100644 --- a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/list/ListPresenter.java +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/list/ListPresenter.java @@ -37,9 +37,12 @@ import info.magnolia.event.EventBus; import info.magnolia.objectfactory.ComponentProvider; import info.magnolia.ui.workbench.AbstractContentPresenter; import info.magnolia.ui.workbench.column.definition.ColumnDefinition; + import info.magnolia.ui.workbench.container.AbstractJcrContainer; import info.magnolia.ui.workbench.definition.WorkbenchDefinition; +import info.magnolia.ui.workbench.tree.HierarchicalJcrContainer; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -55,16 +58,17 @@ public class ListPresenter extends AbstractContentPresenter implements ListView. protected AbstractJcrContainer container; @Inject - public ListPresenter(final ListView view, final ComponentProvider componentProvider) { + public ListPresenter(final ListView view, final ComponentProvider componentProvider, HierarchicalJcrContainer container) { super(componentProvider); this.view = view; + this.container = container; } @Override public ListView start(WorkbenchDefinition workbench, EventBus eventBus, String viewTypeName) { super.start(workbench, eventBus, viewTypeName); - this.container = createContainer(workbench); + //this.container = createContainer(workbench); view.setListener(this); view.setContainer(container); @@ -100,7 +104,11 @@ public class ListPresenter extends AbstractContentPresenter implements ListView. @Override public void select(List itemIds) { - view.select(itemIds); + List objectIds = new ArrayList(); + for (Object itemId : itemIds) { + objectIds.add(itemId); + } + view.select(objectIds); } @Override @@ -114,6 +122,7 @@ public class ListPresenter extends AbstractContentPresenter implements ListView. return new FlatJcrContainer(workbench); } + @Override protected AbstractJcrContainer getContainer() { return container; } diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/list/ListViewImpl.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/list/ListViewImpl.java index cb58238..596da1e 100644 --- a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/list/ListViewImpl.java +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/list/ListViewImpl.java @@ -123,12 +123,12 @@ public class ListViewImpl implements ListView { log.debug("Handle value change Event: {}:{} for listener {}", value.getClass(), value, listener); if (listener != null) { - Set items; + Set items; if (value instanceof Set) { items = (Set) value; } else { - items = new LinkedHashSet(); - items.add((String) value); + items = new LinkedHashSet(); + items.add(value); } listener.onItemSelection(items); } @@ -142,21 +142,21 @@ public class ListViewImpl implements ListView { if (event.getButton() == MouseButton.RIGHT) { if (listener != null) { - listener.onRightClick(event.getItem(), event.getClientX(), event.getClientY()); + listener.onRightClick(String.valueOf(event.getItemId()), event.getClientX(), event.getClientY()); } } else if (event.isDoubleClick()) { if (listener != null) { - listener.onDoubleClick(event.getItem()); + listener.onDoubleClick(String.valueOf(event.getItemId())); } } else { Object value = table.getValue(); if (value != null) { - Set items; + Set items; if (value instanceof Set) { - items = (Set) value; + items = (Set) value; } else { - items = new LinkedHashSet(); - items.add((String) value); + items = new LinkedHashSet(); + items.add(value); } if (items.size() == 1 && items.iterator().next().equals(event.getItemId())) { table.setValue(null); @@ -217,10 +217,10 @@ public class ListViewImpl implements ListView { } @Override - public void select(List itemIds) { + public void select(List itemIds) { table.setValue(null); if (itemIds != null && !itemIds.isEmpty()) { - for (String id : itemIds) { + for (Object id : itemIds) { table.select(id); } } @@ -228,7 +228,7 @@ public class ListViewImpl implements ListView { } @Override - public void expand(String itemId) { + public void expand(Object itemId) { } @Override diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/search/SearchPresenter.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/search/SearchPresenter.java index 13162fa..0ce21fe 100644 --- a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/search/SearchPresenter.java +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/search/SearchPresenter.java @@ -36,6 +36,7 @@ package info.magnolia.ui.workbench.search; import info.magnolia.objectfactory.ComponentProvider; import info.magnolia.ui.workbench.definition.WorkbenchDefinition; import info.magnolia.ui.workbench.list.ListPresenter; +import info.magnolia.ui.workbench.tree.HierarchicalJcrContainer; import javax.inject.Inject; @@ -45,8 +46,8 @@ import javax.inject.Inject; public class SearchPresenter extends ListPresenter implements SearchView.Listener { @Inject - public SearchPresenter(SearchView view, ComponentProvider componentProvider) { - super(view, componentProvider); + public SearchPresenter(SearchView view, ComponentProvider componentProvider, HierarchicalJcrContainer container) { + super(view, componentProvider, container); } @Override diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/thumbnail/ThumbnailContainer.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/thumbnail/ThumbnailContainer.java index 4bb482a..699efe6 100644 --- a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/thumbnail/ThumbnailContainer.java +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/thumbnail/ThumbnailContainer.java @@ -47,12 +47,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; -import javax.jcr.NodeIterator; -import javax.jcr.RepositoryException; -import javax.jcr.query.Query; -import javax.jcr.query.QueryManager; -import javax.jcr.query.QueryResult; - import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -143,26 +137,26 @@ public class ThumbnailContainer extends AbstractInMemoryContainer getAllIdentifiers(final String workspaceName) { List uuids = new ArrayList(); - final String query = constructQuery(); - try { - QueryManager qm = MgnlContext.getJCRSession(workspaceName).getWorkspace().getQueryManager(); - Query q = qm.createQuery(query, Query.JCR_SQL2); - - log.debug("Executing query statement [{}] on workspace [{}]", query, workspaceName); - long start = System.currentTimeMillis(); - - QueryResult queryResult = q.execute(); - NodeIterator iter = queryResult.getNodes(); - - while (iter.hasNext()) { - uuids.add(iter.nextNode().getIdentifier()); - } - - log.debug("Done collecting {} nodes in {}ms", uuids.size(), System.currentTimeMillis() - start); - - } catch (RepositoryException e) { - throw new RuntimeRepositoryException(e); - } +// final String query = constructQuery(); +// try { +// QueryManager qm = MgnlContext.getJCRSession(workspaceName).getWorkspace().getQueryManager(); +// Query q = qm.createQuery(query, Query.JCR_SQL2); +// +// log.debug("Executing query statement [{}] on workspace [{}]", query, workspaceName); +// long start = System.currentTimeMillis(); +// +// QueryResult queryResult = q.execute(); +// NodeIterator iter = queryResult.getNodes(); +// +// while (iter.hasNext()) { +// uuids.add(iter.nextNode().getIdentifier()); +// } +// +// log.debug("Done collecting {} nodes in {}ms", uuids.size(), System.currentTimeMillis() - start); +// +// } catch (RepositoryException e) { +// throw new RuntimeRepositoryException(e); +// } return uuids; } diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/thumbnail/ThumbnailPresenter.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/thumbnail/ThumbnailPresenter.java index dd94f73..f9a80ac 100644 --- a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/thumbnail/ThumbnailPresenter.java +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/thumbnail/ThumbnailPresenter.java @@ -33,30 +33,22 @@ */ package info.magnolia.ui.workbench.thumbnail; -import info.magnolia.context.MgnlContext; import info.magnolia.event.EventBus; import info.magnolia.objectfactory.ComponentProvider; import info.magnolia.ui.imageprovider.ImageProvider; -import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter; -import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter; import info.magnolia.ui.workbench.AbstractContentPresenter; import info.magnolia.ui.workbench.ContentView; import info.magnolia.ui.workbench.definition.WorkbenchDefinition; -import info.magnolia.ui.workbench.thumbnail.ThumbnailContainer.ThumbnailItem; +import java.util.ArrayList; import java.util.List; import java.util.Set; import javax.inject.Inject; -import javax.jcr.Node; -import javax.jcr.RepositoryException; -import javax.jcr.Session; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.vaadin.data.Item; - /** * The ThumbnailPresenter is responsible for creating, configuring and updating a thumbnail grid of items according to the workbench definition. */ @@ -104,42 +96,26 @@ public class ThumbnailPresenter extends AbstractContentPresenter implements Thum } @Override - public void onItemSelection(Set items) { - super.onItemSelection(items); + public void onItemSelection(Set itemIds) { + super.onItemSelection(itemIds); } @Override - public void onDoubleClick(Item item) { - JcrItemAdapter jcrItem = getJcrItemByThumbnailItem(item); - super.onDoubleClick(jcrItem); + public void onDoubleClick(Object itemId) { + super.onDoubleClick(itemId); } @Override - public void onRightClick(Item item, int clickX, int clickY) { - JcrItemAdapter jcrItem = getJcrItemByThumbnailItem(item); - super.onRightClick(jcrItem, clickX, clickY); + public void onRightClick(Object itemId, int clickX, int clickY) { + super.onRightClick(itemId, clickX, clickY); } @Override public void select(List itemIds) { - view.select(itemIds); - } - - /** - * Thumbnail container uses specific Thumbnail items, so we have to convert those into JcrItemAdapters. - */ - private JcrItemAdapter getJcrItemByThumbnailItem(final Item item) { - if (item instanceof ThumbnailItem) { - String itemId = ((ThumbnailItem) item).getItemId(); - try { - Session session = MgnlContext.getJCRSession(workbenchDefinition.getWorkspace()); - final Node imageNode = session.getNodeByIdentifier(itemId); - return new JcrNodeAdapter(imageNode); - } catch (RepositoryException e) { - log.error(e.getMessage()); - } + List objectIds = new ArrayList(); + for (Object itemId : itemIds) { + objectIds.add(itemId); } - return null; + view.select(objectIds); } - } diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/thumbnail/ThumbnailViewImpl.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/thumbnail/ThumbnailViewImpl.java index 4c9f4bd..c581d0e 100644 --- a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/thumbnail/ThumbnailViewImpl.java +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/thumbnail/ThumbnailViewImpl.java @@ -43,7 +43,6 @@ import java.util.List; import java.util.Set; import com.vaadin.data.Container; -import com.vaadin.data.Item; import com.vaadin.ui.Component; /** @@ -66,7 +65,7 @@ public class ThumbnailViewImpl implements ThumbnailView { @Override public void onThumbnailSelected(final String itemId) { - Set items = new LinkedHashSet(); + Set items = new LinkedHashSet(); items.add(itemId); listener.onItemSelection(items); } @@ -76,8 +75,7 @@ public class ThumbnailViewImpl implements ThumbnailView { @Override public void onThumbnailDblClicked(final String itemId) { - Item node = thumbnailLayout.getContainerDataSource().getItem(itemId); - listener.onDoubleClick(node); + listener.onDoubleClick(itemId); } }); @@ -85,11 +83,10 @@ public class ThumbnailViewImpl implements ThumbnailView { @Override public void onThumbnailRightClicked(final String itemId, int clickX, int clickY) { - Item node = thumbnailLayout.getContainerDataSource().getItem(itemId); - Set items = new LinkedHashSet(); + Set items = new LinkedHashSet(); items.add(itemId); listener.onItemSelection(items); - listener.onRightClick(node, clickX, clickY); + listener.onRightClick(itemId, clickX, clickY); } }); } @@ -100,11 +97,11 @@ public class ThumbnailViewImpl implements ThumbnailView { } @Override - public void select(List itemIds) { + public void select(List itemIds) { // ThumbnailLayout only supports single selection and because the client requests thumbnails we set the // selected itemId so it can update selection when that happens - String itemId = itemIds == null || itemIds.isEmpty() ? null : itemIds.get(0); - thumbnailLayout.setSelectedItemId(itemId); + Object itemId = itemIds == null || itemIds.isEmpty() ? null : itemIds.get(0); + thumbnailLayout.setSelectedItemId((String)itemId); } @Override @@ -140,7 +137,7 @@ public class ThumbnailViewImpl implements ThumbnailView { } @Override - public void expand(String itemId) { + public void expand(Object itemId) { } } diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/tree/TreePresenter.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/tree/TreePresenter.java index 600c7ca..805c608 100644 --- a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/tree/TreePresenter.java +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/tree/TreePresenter.java @@ -63,8 +63,8 @@ public class TreePresenter extends ListPresenter implements TreeView.Listener { private static final Logger log = LoggerFactory.getLogger(TreePresenter.class); @Inject - public TreePresenter(TreeView view, ComponentProvider componentProvider) { - super(view, componentProvider); + public TreePresenter(TreeView view, ComponentProvider componentProvider, HierarchicalJcrContainer container) { + super(view, componentProvider, container); } @Override diff --git a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/tree/TreeViewImpl.java b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/tree/TreeViewImpl.java index 1533938..723f90a 100644 --- a/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/tree/TreeViewImpl.java +++ b/magnolia-ui-workbench/src/main/java/info/magnolia/ui/workbench/tree/TreeViewImpl.java @@ -57,7 +57,7 @@ import com.vaadin.ui.Table.TableDragMode; import com.vaadin.ui.TreeTable; /** - * Vaadin UI component that displays a tree. + * Default Vaadin implementation of the tree view. */ public class TreeViewImpl extends ListViewImpl implements TreeView { @@ -138,8 +138,8 @@ public class TreeViewImpl extends ListViewImpl implements TreeView { } @Override - public void select(List itemIds) { - String firstItemId = itemIds == null || itemIds.isEmpty() ? null : itemIds.get(0); + public void select(List itemIds) { + Object firstItemId = itemIds == null || itemIds.isEmpty() ? null : itemIds.get(0); if (firstItemId == null || treeTable.isSelected(firstItemId)) { return; } @@ -147,54 +147,54 @@ public class TreeViewImpl extends ListViewImpl implements TreeView { expandTreeToNode(firstItemId, false); treeTable.setValue(null); - for (String id : itemIds) { + for (Object id : itemIds) { treeTable.select(id); } treeTable.setCurrentPageFirstItemId(firstItemId); } @Override - public void expand(String itemId) { + public void expand(Object itemId) { expandTreeToNode(itemId, true); } - private void expandTreeToNode(String nodeId, boolean expandNode) { - HierarchicalJcrContainer container = (HierarchicalJcrContainer) treeTable.getContainerDataSource(); - String workbenchPath = container.getWorkbenchDefinition().getPath(); - - try { - Item item = container.getJcrItem(nodeId); - if (item == null || !item.getPath().contains(workbenchPath)) { - return; - } - - // Determine node to expand. - Node node = null; - - if (item instanceof Property) { - node = item.getParent(); - } else { - - if (expandNode) { - node = (Node) item; - } else { - // Check if item is root. - if (!StringUtils.equals(((Node) item).getPath(), workbenchPath)) { - node = item.getParent(); - } - } - - } - - // as long as parent is within the scope of the workbench - while (node != null && !StringUtils.equals(node.getPath(), workbenchPath)) { - treeTable.setCollapsed(node.getIdentifier(), false); - node = node.getParent(); - } - - } catch (RepositoryException e) { - log.warn("Could not collect the parent hierarchy of node {}", nodeId, e); - } + private void expandTreeToNode(Object nodeId, boolean expandNode) { +// HierarchicalJcrContainer container = (HierarchicalJcrContainer) treeTable.getContainerDataSource(); +// String workbenchPath = container.getWorkbenchDefinition().getPath(); +// +// try { +// Item item = container.getJcrItem(nodeId); +// if (item == null || !item.getPath().contains(workbenchPath)) { +// return; +// } +// +// // Determine node to expand. +// Node node = null; +// +// if (item instanceof Property) { +// node = item.getParent(); +// } else { +// +// if (expandNode) { +// node = (Node) item; +// } else { +// // Check if item is root. +// if (!StringUtils.equals(((Node) item).getPath(), workbenchPath)) { +// node = item.getParent(); +// } +// } +// +// } +// +// // as long as parent is within the scope of the workbench +// while (node != null && !StringUtils.equals(node.getPath(), workbenchPath)) { +// treeTable.setCollapsed(node.getIdentifier(), false); +// node = node.getParent(); +// } +// +// } catch (RepositoryException e) { +// log.warn("Could not collect the parent hierarchy of node {}", nodeId, e); +// } } @Override diff --git a/magnolia-ui-workbench/src/test/java/info/magnolia/ui/workbench/container/AbstractJcrContainerTest.java b/magnolia-ui-workbench/src/test/java/info/magnolia/ui/workbench/container/AbstractJcrContainerTest.java index 60be7cf..6ea4627 100644 --- a/magnolia-ui-workbench/src/test/java/info/magnolia/ui/workbench/container/AbstractJcrContainerTest.java +++ b/magnolia-ui-workbench/src/test/java/info/magnolia/ui/workbench/container/AbstractJcrContainerTest.java @@ -38,9 +38,9 @@ import static org.junit.Assert.*; import info.magnolia.context.MgnlContext; import info.magnolia.jcr.util.NodeTypes; import info.magnolia.test.RepositoryTestCase; -import info.magnolia.ui.api.ModelConstants; import info.magnolia.ui.vaadin.integration.jcr.DefaultProperty; import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter; +import info.magnolia.ui.vaadin.integration.jcr.ModelConstants; import info.magnolia.ui.workbench.column.definition.PropertyTypeColumnDefinition; import info.magnolia.ui.workbench.definition.ConfiguredContentPresenterDefinition; import info.magnolia.ui.workbench.definition.ConfiguredNodeTypeDefinition; diff --git a/magnolia-ui-workbench/src/test/java/info/magnolia/ui/workbench/content/ContentPresenterTest.java b/magnolia-ui-workbench/src/test/java/info/magnolia/ui/workbench/content/ContentPresenterTest.java index 59cb568..cb8cfe4 100644 --- a/magnolia-ui-workbench/src/test/java/info/magnolia/ui/workbench/content/ContentPresenterTest.java +++ b/magnolia-ui-workbench/src/test/java/info/magnolia/ui/workbench/content/ContentPresenterTest.java @@ -130,7 +130,7 @@ public class ContentPresenterTest { ArgumentCaptor argument = ArgumentCaptor.forClass(ItemDoubleClickedEvent.class); verify(eventBus).fireEvent(argument.capture()); assertEquals(TEST_WORKSPACE_NAME, argument.getValue().getWorkspace()); - assertEquals(testNode.getIdentifier(), argument.getValue().getPath()); + assertEquals(testNode.getIdentifier(), argument.getValue().getId()); } @Test diff --git a/magnolia-ui-workbench/src/test/java/info/magnolia/ui/workbench/search/SearchJcrContainerTest.java b/magnolia-ui-workbench/src/test/java/info/magnolia/ui/workbench/search/SearchJcrContainerTest.java index ba81841..aa1a55a 100644 --- a/magnolia-ui-workbench/src/test/java/info/magnolia/ui/workbench/search/SearchJcrContainerTest.java +++ b/magnolia-ui-workbench/src/test/java/info/magnolia/ui/workbench/search/SearchJcrContainerTest.java @@ -37,7 +37,7 @@ import static org.junit.Assert.*; import info.magnolia.context.MgnlContext; import info.magnolia.test.RepositoryTestCase; -import info.magnolia.ui.api.ModelConstants; +import info.magnolia.ui.vaadin.integration.jcr.ModelConstants; import info.magnolia.ui.workbench.column.definition.PropertyTypeColumnDefinition; import info.magnolia.ui.workbench.container.OrderBy; import info.magnolia.ui.workbench.definition.ConfiguredContentPresenterDefinition; diff --git a/pages/src/main/java/info/magnolia/pages/app/action/CreateComponentAction.java b/pages/src/main/java/info/magnolia/pages/app/action/CreateComponentAction.java index b1f2431..d225b8b 100644 --- a/pages/src/main/java/info/magnolia/pages/app/action/CreateComponentAction.java +++ b/pages/src/main/java/info/magnolia/pages/app/action/CreateComponentAction.java @@ -43,7 +43,7 @@ import info.magnolia.registry.RegistrationException; import info.magnolia.rendering.template.TemplateDefinition; import info.magnolia.rendering.template.registry.TemplateDefinitionRegistry; import info.magnolia.ui.admincentral.dialog.action.CancelDialogActionDefinition; -import info.magnolia.ui.api.ModelConstants; +import info.magnolia.ui.vaadin.integration.jcr.ModelConstants; import info.magnolia.ui.api.action.AbstractAction; import info.magnolia.ui.api.action.ActionExecutionException; import info.magnolia.ui.api.app.SubAppContext; diff --git a/pages/src/main/java/info/magnolia/pages/app/availability/PageHasSubpagesAndIsNotDeletedRule.java b/pages/src/main/java/info/magnolia/pages/app/availability/PageHasSubpagesAndIsNotDeletedRule.java index a875d2b..6d19bdc 100644 --- a/pages/src/main/java/info/magnolia/pages/app/availability/PageHasSubpagesAndIsNotDeletedRule.java +++ b/pages/src/main/java/info/magnolia/pages/app/availability/PageHasSubpagesAndIsNotDeletedRule.java @@ -37,7 +37,7 @@ import info.magnolia.ui.api.availability.AbstractAvailabilityRule; import info.magnolia.ui.api.availability.AvailabilityRule; import info.magnolia.ui.api.availability.IsNotDeletedRule; -import javax.jcr.Item; +import com.vaadin.data.Item; /** * This rule returns true, if the item is node of the mgnl:page type, has a subnode of the same type, and is not deleted (i.e. has not the mgnl:deleted mixin type). diff --git a/pages/src/main/java/info/magnolia/pages/app/availability/PageHasSubpagesRule.java b/pages/src/main/java/info/magnolia/pages/app/availability/PageHasSubpagesRule.java index 3cf4c1a..5b72a02 100644 --- a/pages/src/main/java/info/magnolia/pages/app/availability/PageHasSubpagesRule.java +++ b/pages/src/main/java/info/magnolia/pages/app/availability/PageHasSubpagesRule.java @@ -36,13 +36,16 @@ package info.magnolia.pages.app.availability; import info.magnolia.jcr.util.NodeTypes; import info.magnolia.jcr.util.NodeUtil; import info.magnolia.ui.api.availability.AbstractAvailabilityRule; -import javax.jcr.Item; +import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter; + import javax.jcr.Node; import javax.jcr.RepositoryException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.vaadin.data.Item; + /** * This rule returns true, if the item is node of the mgnl:page type and has a subnode of the same type. */ @@ -52,9 +55,16 @@ public class PageHasSubpagesRule extends AbstractAvailabilityRule { @Override public boolean isAvailableForItem(Item item) { + if (!(item instanceof JcrItemAdapter)) { + return false; + } + + JcrItemAdapter jcrItemAdapter = (JcrItemAdapter)item; + javax.jcr.Item jcrItem = jcrItemAdapter.getJcrItem(); + // item must be a Node - if (item != null && item.isNode()) { - Node node = (Node) item; + if (item != null && jcrItem.isNode()) { + Node node = (Node) jcrItem; try { // node must be of the Page type if (NodeUtil.isNodeType(node, NodeTypes.Page.NAME)) { diff --git a/pages/src/main/java/info/magnolia/pages/app/editor/PagesEditorSubApp.java b/pages/src/main/java/info/magnolia/pages/app/editor/PagesEditorSubApp.java index cf6a19d..0694629 100644 --- a/pages/src/main/java/info/magnolia/pages/app/editor/PagesEditorSubApp.java +++ b/pages/src/main/java/info/magnolia/pages/app/editor/PagesEditorSubApp.java @@ -47,6 +47,7 @@ import info.magnolia.pages.app.editor.event.ComponentMoveEvent; import info.magnolia.pages.app.editor.event.NodeSelectedEvent; import info.magnolia.repository.RepositoryConstants; import info.magnolia.ui.actionbar.ActionbarPresenter; +import info.magnolia.ui.actionbar.ActionbarView; import info.magnolia.ui.actionbar.definition.ActionbarDefinition; import info.magnolia.ui.actionbar.definition.ActionbarGroupDefinition; import info.magnolia.ui.actionbar.definition.ActionbarItemDefinition; @@ -69,7 +70,6 @@ import info.magnolia.ui.contentapp.detail.DetailLocation; import info.magnolia.ui.contentapp.detail.DetailSubAppDescriptor; import info.magnolia.ui.contentapp.detail.DetailView; import info.magnolia.ui.framework.app.BaseSubApp; -import info.magnolia.ui.vaadin.actionbar.ActionbarView; import info.magnolia.ui.vaadin.editor.PageEditorListener; import info.magnolia.ui.vaadin.editor.gwt.shared.PlatformType; import info.magnolia.ui.vaadin.editor.pagebar.PageBarView; @@ -82,6 +82,7 @@ import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter; import java.util.List; import java.util.Locale; +import java.util.Map; import javax.inject.Inject; import javax.inject.Named; @@ -159,13 +160,17 @@ public class PagesEditorSubApp extends BaseSubApp impleme DetailLocation detailLocation = DetailLocation.wrap(location); super.start(detailLocation); + ActionbarDefinition actionbarDefinition = ((ContentSubAppDescriptor) getSubAppContext().getSubAppDescriptor()).getActionbar(); + Map actionDefinitions = getSubAppContext().getSubAppDescriptor().getActions(); actionbarPresenter.setListener(this); + ActionbarView actionbar = actionbarPresenter.start(actionbarDefinition, actionDefinitions); + pageBarView.setListener(this); - ActionbarDefinition actionbarDefinition = ((ContentSubAppDescriptor) getSubAppContext().getSubAppDescriptor()).getActionbar(); - ActionbarView actionbar = actionbarPresenter.start(actionbarDefinition); + view.setActionbarView(actionbar); view.setPageBarView(pageBarView); view.setPageEditorView(pageEditorPresenter.start()); + goToLocation(detailLocation); return view; } @@ -402,18 +407,6 @@ public class PagesEditorSubApp extends BaseSubApp impleme } @Override - public String getLabel(String actionName) { - ActionDefinition actionDefinition = actionExecutor.getActionDefinition(actionName); - return (actionDefinition != null) ? actionDefinition.getLabel() : null; - } - - @Override - public String getIcon(String actionName) { - ActionDefinition actionDefinition = actionExecutor.getActionDefinition(actionName); - return (actionDefinition != null) ? actionDefinition.getIcon() : null; - } - - @Override public void languageSelected(Locale locale) { if (locale != null && !locale.equals(currentLocale)) { this.currentLocale = locale; @@ -511,7 +504,7 @@ public class PagesEditorSubApp extends BaseSubApp impleme for (ActionbarItemDefinition itemDefinition : groupDefinition.getItems()) { String actionName = itemDefinition.getName(); - if (actionExecutor.isAvailable(actionName, node)) { + if (actionExecutor.isAvailable(actionName, new JcrNodeAdapter(node))) { actionbarPresenter.enable(actionName); } else { actionbarPresenter.disable(actionName); diff --git a/pages/src/main/java/info/magnolia/pages/app/editor/PagesEditorSubAppView.java b/pages/src/main/java/info/magnolia/pages/app/editor/PagesEditorSubAppView.java index d3cec5e..6e60517 100644 --- a/pages/src/main/java/info/magnolia/pages/app/editor/PagesEditorSubAppView.java +++ b/pages/src/main/java/info/magnolia/pages/app/editor/PagesEditorSubAppView.java @@ -33,8 +33,8 @@ */ package info.magnolia.pages.app.editor; +import info.magnolia.ui.actionbar.ActionbarView; import info.magnolia.ui.contentapp.ContentSubAppView; -import info.magnolia.ui.vaadin.actionbar.ActionbarView; import info.magnolia.ui.vaadin.editor.PageEditorView; import info.magnolia.ui.vaadin.editor.pagebar.PageBarView; diff --git a/pages/src/main/java/info/magnolia/pages/app/editor/PagesEditorSubAppViewImpl.java b/pages/src/main/java/info/magnolia/pages/app/editor/PagesEditorSubAppViewImpl.java index fccf8c2..fd136fb 100644 --- a/pages/src/main/java/info/magnolia/pages/app/editor/PagesEditorSubAppViewImpl.java +++ b/pages/src/main/java/info/magnolia/pages/app/editor/PagesEditorSubAppViewImpl.java @@ -33,8 +33,8 @@ */ package info.magnolia.pages.app.editor; +import info.magnolia.ui.actionbar.ActionbarView; import info.magnolia.ui.api.view.View; -import info.magnolia.ui.vaadin.actionbar.ActionbarView; import info.magnolia.ui.vaadin.editor.PageEditorView; import info.magnolia.ui.vaadin.editor.pagebar.PageBarView; diff --git a/security-app/src/main/java/info/magnolia/security/app/action/availability/IsNotCurrentUserRule.java b/security-app/src/main/java/info/magnolia/security/app/action/availability/IsNotCurrentUserRule.java index 18d175c..1c863a3 100644 --- a/security-app/src/main/java/info/magnolia/security/app/action/availability/IsNotCurrentUserRule.java +++ b/security-app/src/main/java/info/magnolia/security/app/action/availability/IsNotCurrentUserRule.java @@ -35,14 +35,15 @@ package info.magnolia.security.app.action.availability; import info.magnolia.context.MgnlContext; import info.magnolia.ui.api.availability.AbstractAvailabilityRule; +import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter; -import javax.jcr.Item; -import javax.jcr.Node; import javax.jcr.RepositoryException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.vaadin.data.Item; + /** * The rule to verify that the item does not represent the current user. */ @@ -52,11 +53,19 @@ public class IsNotCurrentUserRule extends AbstractAvailabilityRule { @Override protected boolean isAvailableForItem(Item item) { - if (item == null || !item.isNode()) { + if (!(item instanceof JcrItemAdapter)) { + return true; + } + + JcrItemAdapter jcrItemAdapter = (JcrItemAdapter)item; + javax.jcr.Item jcrItem = jcrItemAdapter.getJcrItem(); + + + if (!jcrItem.isNode()) { return true; } try { - String nodeName = ((Node) item).getName(); + String nodeName = jcrItem.getName(); return !nodeName.equals(MgnlContext.getUser().getName()); } catch (RepositoryException ex) { log.warn("Error verifying availability for item [{}]: " + ex.getMessage(), item); diff --git a/security-app/src/main/java/info/magnolia/security/app/container/RoleTreePresenter.java b/security-app/src/main/java/info/magnolia/security/app/container/RoleTreePresenter.java index e66a33a..cc7df1c 100644 --- a/security-app/src/main/java/info/magnolia/security/app/container/RoleTreePresenter.java +++ b/security-app/src/main/java/info/magnolia/security/app/container/RoleTreePresenter.java @@ -44,8 +44,8 @@ import info.magnolia.ui.workbench.tree.TreeView; */ public class RoleTreePresenter extends TreePresenter { - public RoleTreePresenter(TreeView view, ComponentProvider componentProvider) { - super(view, componentProvider); + public RoleTreePresenter(TreeView view, ComponentProvider componentProvider, HierarchicalJcrContainer container) { + super(view, componentProvider, container); } @Override diff --git a/security-app/src/main/java/info/magnolia/security/app/container/UserTreePresenter.java b/security-app/src/main/java/info/magnolia/security/app/container/UserTreePresenter.java index bdf92a2..b8db217 100644 --- a/security-app/src/main/java/info/magnolia/security/app/container/UserTreePresenter.java +++ b/security-app/src/main/java/info/magnolia/security/app/container/UserTreePresenter.java @@ -44,8 +44,8 @@ import info.magnolia.ui.workbench.tree.TreeView; */ public class UserTreePresenter extends TreePresenter { - public UserTreePresenter(TreeView view, ComponentProvider componentProvider) { - super(view, componentProvider); + public UserTreePresenter(TreeView view, ComponentProvider componentProvider, HierarchicalJcrContainer container) { + super(view, componentProvider, container); } @Override diff --git a/security-app/src/main/java/info/magnolia/security/app/dialog/action/SaveRoleDialogAction.java b/security-app/src/main/java/info/magnolia/security/app/dialog/action/SaveRoleDialogAction.java index e93c647..b15886a 100644 --- a/security-app/src/main/java/info/magnolia/security/app/dialog/action/SaveRoleDialogAction.java +++ b/security-app/src/main/java/info/magnolia/security/app/dialog/action/SaveRoleDialogAction.java @@ -48,7 +48,7 @@ import info.magnolia.security.app.dialog.field.WorkspaceAccessFieldFactory; import info.magnolia.security.app.util.UsersWorkspaceUtil; import info.magnolia.ui.admincentral.dialog.action.SaveDialogAction; import info.magnolia.ui.admincentral.dialog.action.SaveDialogActionDefinition; -import info.magnolia.ui.api.ModelConstants; +import info.magnolia.ui.vaadin.integration.jcr.ModelConstants; import info.magnolia.ui.api.action.ActionExecutionException; import info.magnolia.ui.form.EditorCallback; import info.magnolia.ui.form.EditorValidator; diff --git a/security-app/src/main/java/info/magnolia/security/app/dialog/action/SaveUserDialogAction.java b/security-app/src/main/java/info/magnolia/security/app/dialog/action/SaveUserDialogAction.java index 663f28d..145bc41 100644 --- a/security-app/src/main/java/info/magnolia/security/app/dialog/action/SaveUserDialogAction.java +++ b/security-app/src/main/java/info/magnolia/security/app/dialog/action/SaveUserDialogAction.java @@ -45,7 +45,7 @@ import info.magnolia.jcr.util.PropertyUtil; import info.magnolia.security.app.util.UsersWorkspaceUtil; import info.magnolia.ui.admincentral.dialog.action.SaveDialogAction; import info.magnolia.ui.admincentral.dialog.action.SaveDialogActionDefinition; -import info.magnolia.ui.api.ModelConstants; +import info.magnolia.ui.vaadin.integration.jcr.ModelConstants; import info.magnolia.ui.api.action.ActionExecutionException; import info.magnolia.ui.form.EditorCallback; import info.magnolia.ui.form.EditorValidator; diff --git a/security-app/src/main/java/info/magnolia/security/app/dialog/field/WorkspaceAccessFieldFactory.java b/security-app/src/main/java/info/magnolia/security/app/dialog/field/WorkspaceAccessFieldFactory.java index 99827ca..d3421ff 100644 --- a/security-app/src/main/java/info/magnolia/security/app/dialog/field/WorkspaceAccessFieldFactory.java +++ b/security-app/src/main/java/info/magnolia/security/app/dialog/field/WorkspaceAccessFieldFactory.java @@ -36,7 +36,7 @@ package info.magnolia.security.app.dialog.field; import info.magnolia.cms.security.Permission; import info.magnolia.i18nsystem.SimpleTranslator; import info.magnolia.jcr.RuntimeRepositoryException; -import info.magnolia.ui.api.ModelConstants; +import info.magnolia.ui.vaadin.integration.jcr.ModelConstants; import info.magnolia.ui.api.app.ChooseDialogCallback; import info.magnolia.ui.api.context.UiContext; import info.magnolia.ui.contentapp.field.WorkbenchFieldDefinition; diff --git a/security-app/src/test/java/info/magnolia/security/app/dialog/action/SaveRoleDialogActionTest.java b/security-app/src/test/java/info/magnolia/security/app/dialog/action/SaveRoleDialogActionTest.java index 4bfabee..3ea2a4f 100644 --- a/security-app/src/test/java/info/magnolia/security/app/dialog/action/SaveRoleDialogActionTest.java +++ b/security-app/src/test/java/info/magnolia/security/app/dialog/action/SaveRoleDialogActionTest.java @@ -58,7 +58,7 @@ import info.magnolia.security.app.dialog.field.WorkspaceAccessFieldFactory; import info.magnolia.test.ComponentsTestUtil; import info.magnolia.test.RepositoryTestCase; import info.magnolia.test.mock.MockWebContext; -import info.magnolia.ui.api.ModelConstants; +import info.magnolia.ui.vaadin.integration.jcr.ModelConstants; import info.magnolia.ui.api.action.ActionExecutionException; import info.magnolia.ui.form.EditorCallback; import info.magnolia.ui.form.EditorValidator; -- 1.8.3.4 (Apple Git-47)