Project

General

Profile

Download (9.39 KB) Statistics
| Branch: | Tag: | Revision:
1
package eu.etaxonomy.vaadin.ui.navigation;
2

    
3
import java.util.Arrays;
4
import java.util.List;
5
import java.util.Stack;
6

    
7
import org.apache.commons.lang3.StringUtils;
8
import org.apache.log4j.Logger;
9
import org.springframework.beans.factory.annotation.Autowired;
10
import org.springframework.context.ApplicationContext;
11
import org.springframework.context.annotation.Lazy;
12
import org.vaadin.spring.events.EventBus;
13
import org.vaadin.spring.events.annotation.EventBusListenerMethod;
14

    
15
import com.vaadin.navigator.ViewChangeListener;
16
import com.vaadin.navigator.ViewDisplay;
17
import com.vaadin.spring.annotation.SpringView;
18
import com.vaadin.spring.annotation.UIScope;
19
import com.vaadin.spring.navigator.SpringNavigator;
20
import com.vaadin.spring.navigator.SpringViewProvider;
21
import com.vaadin.ui.Field;
22
import com.vaadin.ui.UI;
23
import com.vaadin.ui.Window;
24

    
25
import eu.etaxonomy.cdm.vaadin.event.AbstractEditorAction.EditorActionContext;
26
import eu.etaxonomy.vaadin.mvp.AbstractEditorPresenter;
27
import eu.etaxonomy.vaadin.mvp.AbstractPopupEditor;
28
import eu.etaxonomy.vaadin.mvp.ApplicationView;
29
import eu.etaxonomy.vaadin.ui.UIInitializedEvent;
30
import eu.etaxonomy.vaadin.ui.view.DoneWithPopupEvent;
31
import eu.etaxonomy.vaadin.ui.view.PopEditorOpenedEvent;
32
import eu.etaxonomy.vaadin.ui.view.PopupView;
33

    
34
@UIScope
35
public class NavigationManagerBean extends SpringNavigator implements NavigationManager {
36

    
37
	private static final long serialVersionUID = 6599898650948333853L;
38

    
39
	private final static Logger logger = Logger.getLogger(NavigationManagerBean.class);
40

    
41
	// injecting the viewDisplay as spring bean causes problems with older cdm vaadin code
42
	// SingleComponentContainerViewDisplay for example can't be used
43
	// the viewDisplay should be configurable per UI therefore it seems more elegant to
44
	// let the UI pass the viewDisplay to the Navigator
45
//	@Autowired
46
	private ViewDisplay viewDisplay;
47

    
48
	@Autowired
49
	private SpringViewProvider viewProvider;
50

    
51
	@Autowired
52
	private List<ViewChangeListener> viewChangeListeners;
53

    
54
	@Autowired
55
	protected ApplicationContext applicationContext;
56

    
57
	protected EventBus.UIEventBus uiEventBus;
58

    
59
    @Autowired
60
    protected void setViewEventBus(EventBus.UIEventBus uiEventBus){
61
        this.uiEventBus = uiEventBus;
62
        uiEventBus.subscribe(this);
63
    }
64

    
65
//    /**
66
//     * This reference will cause the scoped PermissionDebugUtils being initialized.
67
//     * It is not used in this class but attaches itself to the vaadin session
68
//     * from where it will be accessible via VaadinUserHelper.fromSession()
69
//     *
70
//     * <b>NOTE:</b> PermissionDebugUtils is only available if the spring profile "debug" is active,
71
//     * See
72
//     */
73
//    @Autowired(required=false)
74
//    private PermissionDebugUtils permissionDebugUtils;
75

    
76
	private PopupViewRegistration popupViewRegistration;
77

    
78
	private String defaultViewName = null;
79

    
80
    /*
81
     * Why UriFragmentManager must be initialized lazily:
82
     *
83
     * when the SpringVaadinServlet usually is being instantiated the ServletUIInitHandler(UIInitHandler).getBrowserDetailsUI(VaadinRequest, VaadinSession) method is called which will
84
     * first cause the WebapplicationContext being created. Once this is done the initialization of the UI classes is completed. This means that the UI classes are not readily available
85
     * via Page.getCurrent() which is used in the UriFragmentManager constructor. The NavigationManagerBean is initialized with the WebapplicationContext, that is when the current ui is
86
     * not yet available, therefore the UriFragmentManager must be initialized lazily.
87
     */
88
    @Autowired
89
    @Lazy
90
	private UriFragmentManager uriFragmentManager;
91

    
92

    
93
//	public void setUriFragmentManager(UriFragmentManager uriFragmentManager) {
94
//	    this.uriFragmentManager = uriFragmentManager;
95
//	}
96

    
97

    
98
	public NavigationManagerBean() {
99
	    popupViewRegistration = new PopupViewRegistration();
100
	}
101

    
102
//	private Collection<PopupView> popupViews = new HashSet<>();
103
//	@Lazy
104
//    @Autowired(required=false)
105
//    private void popUpViews(Collection<PopupView> popupViews){
106
//        this.popupViews = popupViews;
107
//        // popupViews.forEach(view -> this.popupViews.put(view.getClass(), view));
108
//    }
109

    
110
    private <P extends PopupView> P findPopupView(Class<P> type){
111
        P viewBean = applicationContext.getBean(type);
112
        if(viewBean == null){
113
            throw new NullPointerException("no popup-view bean of type " + type.getName() + " found");
114
        }
115
        return viewBean;
116
        // return popupViews.stream().filter(p -> p.getClass().equals(type)).findFirst();
117
    }
118

    
119
	@EventBusListenerMethod
120
	protected void onUIInitialized(UIInitializedEvent e) {
121
		init(UI.getCurrent(), uriFragmentManager, viewDisplay);
122
		addProvider(viewProvider);
123
		viewChangeListeners.forEach(vcl -> addViewChangeListener(vcl));
124
	}
125

    
126
	public void navigateTo(String navigationState, boolean fireNavigationEvent) {
127
	    if(StringUtils.isEmpty(navigationState)){
128
            navigationState = defaultViewName;
129
        }
130
		if (fireNavigationEvent) {
131
			navigateTo(navigationState);
132
		} else {
133
			super.navigateTo(navigationState);
134
		}
135
		popupViewRegistration.removeOrphan();
136
	}
137

    
138
	@Override
139
	public void navigateTo(String navigationState) {
140
	    if(StringUtils.isEmpty(navigationState)){
141
	        navigationState = defaultViewName;
142
	    }
143
		super.navigateTo(navigationState);
144
		//eventBus.publishEvent(new NavigationEvent(navigationState));
145
		popupViewRegistration.removeOrphan();
146
	}
147

    
148
	@EventBusListenerMethod
149
	protected void onNavigationEvent(NavigationEvent e) {
150
		navigateTo(e.getViewName(), false);
151
	}
152

    
153
	@Override
154
	public <T extends PopupView> T showInPopup(Class<T> popupType, ApplicationView parentView, Field<?> targetField) {
155

    
156
	    PopupView popupView =  findPopupView(popupType);
157

    
158
	    if(AbstractPopupEditor.class.isAssignableFrom(popupView.getClass())){
159
	        if(parentView instanceof AbstractPopupEditor){
160
	            // retain the chain of EditorActionContexts when starting a new pupupEditor
161
	            Stack<EditorActionContext> parentEditorActionContext = ((AbstractPopupEditor)parentView).getEditorActionContext();
162
	            ((AbstractPopupEditor)popupView).setParentEditorActionContext(parentEditorActionContext);
163
	        }
164
	    }
165

    
166
		Window window = new Window();
167
		window.setCaption(popupView.getWindowCaption());
168
		window.center();
169
		window.setResizable(popupView.isResizable());
170
		// due to issue #6673 (https://dev.e-taxonomy.eu/redmine/issues/6673) popup editors must be modal!
171
		//window.setModal(popupView.isModal());
172
		window.setModal(true);
173
		window.setCaptionAsHtml(popupView.isWindowCaptionAsHtml());
174
		window.setWidth(popupView.getWindowWidth(), popupView.getWindowWidthUnit());
175
		window.setHeight(popupView.getWindowHeight(), popupView.getWindowHeightUnit());
176
		window.setContent(popupView.asComponent());
177
		// TODO need to disallow pressing the close [x] button:
178
		// since window.addCloseListener(e -> popupView.cancel()); will
179
		// cause sending cancel events even if save has been clicked
180
		window.setClosable(popupView.isClosable());
181
		UI.getCurrent().addWindow(window);
182
		popupView.viewEntered();
183
		popupView.focusFirst();
184
		uiEventBus.publish(this, new PopEditorOpenedEvent(this, popupView));
185

    
186
		popupViewRegistration.put(window, parentView, popupView, targetField);
187

    
188
		return (T) popupView;
189
	}
190

    
191
	@Override
192
    public Field<?> targetFieldOf(PopupView popupView){
193
	    return popupViewRegistration.get(popupView);
194
	}
195

    
196
    @EventBusListenerMethod
197
	protected void onDoneWithTheEditor(DoneWithPopupEvent e) {
198

    
199
		PopupView popup = e.getPopup();
200
        Window window = popupViewRegistration.getWindow(popup);
201
		if (window != null) {
202
			window.close();
203
			popupViewRegistration.remove(popup);
204
		}
205
		if(AbstractPopupEditor.class.isAssignableFrom(popup.getClass())){
206
		    ((AbstractPopupEditor)popup).presenter().unsubscribeFromEventBuses();
207
		}
208

    
209
	}
210

    
211
    /**
212
     * {@inheritDoc}
213
     */
214
    @Override
215
    public void reloadCurrentView() {
216
        if(logger.isTraceEnabled()){
217
            logger.trace("reloading " + getState());
218
        }
219
        navigateTo(getState(), false);
220
    }
221

    
222
    /**
223
     * This method requires that the {@SpringView} annotation is used to set the name of the <code>View</code>.
224
     *
225
     * @return the current view name or <code>null</code>
226
     */
227
    @Override
228
    public String getCurrentViewName() {
229
        if(getCurrentView() != null){
230
            SpringView springViewAnnotation = getCurrentView().getClass().getAnnotation(SpringView.class);
231
            if(springViewAnnotation != null){
232
                return springViewAnnotation.name();
233
            }
234
        }
235
        return null;
236
    }
237

    
238
    @Override
239
    public List<String> getCurrentViewParameters(){
240
        String substate = getState();
241
        String currentViewName = getCurrentViewName();
242
        if(currentViewName != null){
243
            substate = substate.replaceAll("^" + currentViewName + "/?", "");
244

    
245
        }
246
        return Arrays.asList(substate.split("/"));
247
    }
248

    
249
    /**
250
     * {@inheritDoc}
251
     */
252
    @Override
253
    public List<AbstractEditorPresenter<?, ?>> getPopupEditorPresenters() {
254
        // TODO Auto-generated method stub
255
        return null;
256
    }
257

    
258

    
259
    /**
260
     * @return the defaultViewName
261
     */
262
    public String getDefaultViewName() {
263
        return defaultViewName;
264
    }
265

    
266

    
267
    /**
268
     * @param defaultViewName the defaultViewName to set
269
     */
270
    public void setDefaultViewName(String defaultViewName) {
271
        this.defaultViewName = defaultViewName;
272
    }
273

    
274
    public void setViewDisplay(ViewDisplay viewDisplay){
275
        this.viewDisplay = viewDisplay;
276
    }
277
}
(4-4/8)