/*
* #%L
* carewebframework
* %%
* Copyright (C) 2008 - 2016 Regenstrief Institute, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This Source Code Form is also subject to the terms of the Health-Related
* Additional Disclaimer of Warranty and Limitation of Liability available at
*
* http://www.carewebframework.org/licensing/disclaimer.
*
* #L%
*/
package org.carewebframework.ui.zk;
import java.util.ArrayList;
import java.util.List;
import org.carewebframework.api.spring.SpringUtil;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.MoveEvent;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zul.Window;
/**
* Manages popups created by framework.
*/
public class PopupManager {
private static final String ATTR_OFFSET = "_popupoffset";
/**
* Move listener catches modal dialog immediately after becoming visible to allow adjustment of
* position.
*/
private class PopupMoveEventListener extends MoveEventListener {
private boolean first = true;
@Override
public void onEvent(MoveEvent event) throws Exception {
if (first) {
first = false;
addOffset((Window) event.getTarget());
} else {
super.onEvent(event);
}
}
}
/**
* Close event removes window from manager.
*/
private class PopupCloseEventListener implements EventListener<Event> {
@Override
public void onEvent(Event event) throws Exception {
unregisterPopup((Window) event.getTarget());
}
}
private final List<Window> active = new ArrayList<>();
/*
* Set the offset size to 22 pixels so that the text of the title bars of nested
* popups can be read on all popups in the stack.
*/
private final int increment = 22;
private boolean disableScript;
/**
* Returns an instance of the popup manager.
*
* @return PopupManager
*/
public static PopupManager getInstance() {
return SpringUtil.getBean("popupManager", PopupManager.class);
}
/**
* No-args constructor
*/
public PopupManager() {
super();
}
/**
* Register a window with the popup manager.
*
* @param window Window to register
*/
public void registerPopup(Window window) {
window.addEventListener(Events.ON_MOVE, new PopupMoveEventListener());
window.addEventListener(Events.ON_CLOSE, new PopupCloseEventListener());
}
/**
* Unregister a window from the event manager.
*
* @param window Window to unregister/remove
*/
public void unregisterPopup(Window window) {
active.remove(window);
}
/**
* Destroy method can be called by IOC container.
*/
public void destroy() {
active.clear();
}
/**
* Add the next offset to the window's top and left positions.
*
* @param window The window.
*/
private void addOffset(Window window) {
if (!disableScript && (!window.inEmbedded())) {
int offset = getNextOffset();
active.add(window);
window.setAttribute(ATTR_OFFSET, offset);
if (offset != 0) {
try {
Clients.evalJavaScript("cwf.offset_window('" + window.getUuid() + "'," + (offset * increment) + ");");
} catch (Throwable e) {
disableScript = true;
}
}
}
}
/**
* Returns the next offset to be used.
*
* @return The next offset.
*/
private int getNextOffset() {
int offset = -1;
for (int i = active.size() - 1; i >= 0; i--) {
Window window = active.get(i);
Integer thisOffset = (Integer) window.getAttribute(ATTR_OFFSET);
if (window.getPage() == null || thisOffset == null) {
active.remove(i);
} else if (window.isVisible()) {
offset = thisOffset;
break;
}
}
return offset > 9 ? 0 : offset + 1;
}
}