/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.portfolio.ui.structel;
import java.util.ArrayList;
import java.util.List;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.components.link.LinkFactory;
import org.olat.core.gui.components.velocity.VelocityContainer;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.controller.BasicController;
import org.olat.core.gui.control.generic.dtabs.Activateable2;
import org.olat.core.id.OLATResourceable;
import org.olat.core.id.context.ContextEntry;
import org.olat.core.id.context.StateEntry;
import org.olat.core.util.Formatter;
import org.olat.core.util.StringHelper;
import org.olat.core.util.resource.OresHelper;
import org.olat.portfolio.EPSecurityCallback;
import org.olat.portfolio.manager.EPFrontendManager;
import org.olat.portfolio.model.structel.EPAbstractMap;
import org.olat.portfolio.model.structel.EPPage;
import org.olat.portfolio.model.structel.PortfolioStructure;
import org.olat.portfolio.model.structel.PortfolioStructureRef;
import org.olat.portfolio.ui.structel.view.EPChangelogController;
import org.olat.portfolio.ui.structel.view.EPTOCReadOnlyController;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Description:<br>
* shows multiple pages in a map and handles the paging of them
*
* <P>
* Initial Date: 23.08.2010 <br>
*
* @author Roman Haag, roman.haag@frentix.com, http://www.frentix.com
*/
public class EPMultiplePageController extends BasicController implements Activateable2 {
private List<PageTab> pageList;
private Controller currentActivePageCtrl;
private EPTOCReadOnlyController tocPageCtrl;
private EPChangelogController changelogPageCtrl;
private final VelocityContainer vC;
private final EPSecurityCallback secCallback;
@Autowired
private EPFrontendManager ePFMgr;
private Link tocLink; // the first tab, link to TOC
private Link changelogLink; // the last tab, link to Changelog
private static final int PAGENUM_TOC = -1; // pagenum of toc (first tab)
private static final int PAGENUM_CL = -2; // pagenum of changelog (last tab)
public EPMultiplePageController(UserRequest ureq, WindowControl wControl, List<PortfolioStructure> pages, EPSecurityCallback secCallback) {
super(ureq, wControl);
this.secCallback = secCallback;
pageList = new ArrayList<>(pages.size());
for(PortfolioStructure page:pages) {
if(page instanceof EPPage) {
pageList.add(new PageTab(page.getKey(), page.getTitle()));
}
}
vC = createVelocityContainer("multiPages");
init(ureq);
putInitialPanel(vC);
}
public EPPage getSelectedPage() {
if (currentActivePageCtrl instanceof EPPageViewController) {
return ((EPPageViewController) currentActivePageCtrl).getPage();
}
return null;
}
/**
* @see org.olat.core.gui.components.form.flexible.impl.FormBasicController#initForm(org.olat.core.gui.components.form.flexible.FormItemContainer,
* org.olat.core.gui.control.Controller, org.olat.core.gui.UserRequest)
*/
protected void init(UserRequest ureq) {
if (pageList != null && pageList.size() != 0) {
// create toc link
tocLink = LinkFactory.createLink("toc", vC, this);
tocLink.setDomReplacementWrapperRequired(false);
tocLink.setUserObject(PAGENUM_TOC);
// create changelog link
changelogLink = LinkFactory.createLink("changelog", vC, this);
changelogLink.setDomReplacementWrapperRequired(false);
changelogLink.setUserObject(PAGENUM_CL);
int i = 1;
List<Link> pageLinkList = new ArrayList<Link>();
for (PageTab page : pageList) {
String pageTitle =StringHelper.escapeHtml(page.getTitle());
String shortPageTitle = Formatter.truncate(pageTitle, 20);
Link pageLink = LinkFactory
.createCustomLink("pageLink" + i, "pageLink" + i, shortPageTitle, Link.LINK + Link.NONTRANSLATED, vC, this);
pageLink.setDomReplacementWrapperRequired(false);
pageLink.setUserObject(i - 1);
pageLink.setTooltip(pageTitle);
pageLinkList.add(pageLink);
i++;
}
vC.contextPut("pageLinkList", pageLinkList);
setAndInitActualPage(ureq, PAGENUM_TOC, false);
}
}
protected void selectPage(UserRequest ureq, PortfolioStructure page) {
int count = 0;
for (PageTab structure : pageList) {
if (structure.getKey().equals(page.getKey())) {
setAndInitActualPage(ureq, count, false);
break;
}
count++;
}
}
/**
*
* @param ureq
* @param pageNum
* @param withComments
*/
private void setAndInitActualPage(UserRequest ureq, int pageNum, boolean withComments) {
disposeNormalPageController();
if (pageNum == -1) {
setAndInitTOCPage(ureq);
} else if (pageNum == PAGENUM_CL) {
setAndInitCLPage(ureq);
} else {
setAndInitNormalPage(ureq, pageNum, withComments);
}
vC.put("pageCtrl", currentActivePageCtrl.getInitialComponent());
vC.contextPut("actualPage", pageNum + 1);
}
/**
* disposes the currentActivePageCtrl if its not the toc and not the
* changelog
*/
private void disposeNormalPageController() {
if (currentActivePageCtrl instanceof EPPageViewController) {
removeAsListenerAndDispose(currentActivePageCtrl);
}
}
/**
*
* @param ureq
*/
private void setAndInitTOCPage(UserRequest ureq) {
// this is the toc
if (tocPageCtrl == null) {
PageTab page = pageList.get(0);
PortfolioStructure map = ePFMgr.loadStructureParent(page);
tocPageCtrl = new EPTOCReadOnlyController(ureq, getWindowControl(), map, secCallback);
listenTo(tocPageCtrl);
} else {
tocPageCtrl.refreshTOC(ureq);
}
disableLINK_LC(false);
disableLink_TOC(true);
currentActivePageCtrl = tocPageCtrl;
addToHistory(ureq, OresHelper.createOLATResourceableType("TOC"), null);
}
/**
*
* @param ureq
*/
private void setAndInitCLPage(UserRequest ureq) {
if (changelogPageCtrl == null) {
changelogPageCtrl = instantiateCLController(ureq);
listenTo(changelogPageCtrl);
} else {
changelogPageCtrl.refreshNewsList();
}
currentActivePageCtrl = changelogPageCtrl;
disableLink_TOC(false);
disableLINK_LC(true);
addToHistory(ureq, OresHelper.createOLATResourceableType("CL"), null);
}
/**
*
* @param ureq
* @return
*/
private EPChangelogController instantiateCLController(UserRequest ureq) {
PageTab page = pageList.get(0);
EPAbstractMap abstrMap = (EPAbstractMap)ePFMgr.loadStructureParent(page);
return new EPChangelogController(ureq, getWindowControl(), abstrMap);
}
/**
*
* @param ureq
* @param pageNumberToInit
* @param withComments
*/
private void setAndInitNormalPage(UserRequest ureq, int pageNumberToInit, boolean withComments) {
PageTab tab = pageList.get(pageNumberToInit);
PortfolioStructure structureElement = ePFMgr.loadPortfolioStructureByKey(tab);
if(structureElement instanceof EPPage) {
EPPage page = (EPPage)structureElement;
PortfolioStructure map = ePFMgr.loadStructureParent(tab);
WindowControl bwControl = addToHistory(ureq, OresHelper.createOLATResourceableInstance(EPPage.class, page.getKey()), null);
currentActivePageCtrl = new EPPageViewController(ureq, bwControl, map, page, withComments, secCallback);
listenTo(currentActivePageCtrl);
// enable toc and changelog links
disableLink_TOC(false);
disableLINK_LC(false);
}
}
private void disableLink_TOC(boolean disable) {
vC.contextPut("toc_enabled", disable);
}
private void disableLINK_LC(boolean disable) {
vC.contextPut("changelog_enabled", disable);
}
@Override
protected void event(UserRequest ureq, Component source, Event event) {
if (source instanceof Link) {
Link link = (Link) source;
int pageNum = PAGENUM_TOC;
try {
pageNum = Integer.parseInt(link.getUserObject().toString());
} catch (NumberFormatException nfe) {
// somehow the link has a invalid pageNum, display the TOC
}
setAndInitActualPage(ureq, pageNum, false);
}
}
/**
* @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
* org.olat.core.gui.control.Controller,
* org.olat.core.gui.control.Event)
*/
@Override
protected void event(UserRequest ureq, Controller source, Event event) {
super.event(ureq, source, event);
if (source == currentActivePageCtrl) {
if (source instanceof EPTOCReadOnlyController || source instanceof EPChangelogController) {
// activate selected structure from toc or changelog
if (event instanceof EPStructureEvent) {
handleEPStructureEvent(ureq, (EPStructureEvent) event);
} else if (event instanceof EPMapKeyEvent) {
handleEPMapKeyEvent(ureq, (EPMapKeyEvent) event);
}
}
}
}
/**
*
* @param ureq
* @param epEv
*/
private void handleEPStructureEvent(UserRequest ureq, EPStructureEvent epEv) {
PortfolioStructure selStruct = epEv.getStructure();
if (epEv.getCommand().equals(EPStructureEvent.SELECT)) {
findAndActivatePage(ureq, selStruct, false);
} else if (epEv.getCommand().equals(EPStructureEvent.SELECT_WITH_COMMENTS)) {
findAndActivatePage(ureq, selStruct, true);
}
}
/**
*
* @param ureq
* @param epEv
*/
private void handleEPMapKeyEvent(UserRequest ureq, EPMapKeyEvent epEv) {
Long mapKey = epEv.getMapKey();
if (mapKey != null && mapKey > 1) {
findAndActivatePageByKey(ureq, mapKey);
} else {
setAndInitActualPage(ureq, PAGENUM_TOC, false);
}
}
@Override
public void activate(UserRequest ureq, List<ContextEntry> entries, StateEntry state) {
if (entries == null || entries.isEmpty())
return;
OLATResourceable ores = entries.get(0).getOLATResourceable();
if ("TOC".equals(ores.getResourceableTypeName())) {
setAndInitActualPage(ureq, PAGENUM_TOC, false);
} else if ("CL".equals(ores.getResourceableTypeName())) {
setAndInitActualPage(ureq, PAGENUM_TOC, false);
} else if ("EPPage".equals(ores.getResourceableTypeName())) {
Long pageKey = ores.getResourceableId();
if (containsPage(pageKey)) {
int pos = indexOfPage(pageKey);
if (pos != -1) {
setAndInitActualPage(ureq, pos, false);
}
}
}
}
private void findAndActivatePage(UserRequest ureq, PortfolioStructure selStruct, boolean withComments) {
if (containsPage(selStruct.getKey())) {
int pos = indexOfPage(selStruct.getKey());
if (pos != -1)
setAndInitActualPage(ureq, pos, withComments);
} else {
// lookup parents, as this could be an artefact or a
// structureElement
PortfolioStructure parentStruct = ePFMgr.loadStructureParent(selStruct);
if (parentStruct != null)
findAndActivatePage(ureq, parentStruct, withComments);
}
}
private void findAndActivatePageByKey(UserRequest ureq, Long key) {
if (containsPage(key)) {
int pos = indexOfPage(key);
if (pos != -1)
setAndInitActualPage(ureq, pos, false);
}
}
/**
* @see org.olat.core.gui.control.DefaultController#doDispose()
*/
@Override
protected void doDispose() {
// nothing
}
private int indexOfPage(Long key) {
if(key == null || pageList == null || pageList.isEmpty()) return -1;
int count=0;
for(PageTab pageTab:pageList) {
if(pageTab.getKey().equals(key)) {
break;
}
count++;
}
return count;
}
private boolean containsPage(Long key) {
if(key == null || pageList == null || pageList.isEmpty()) return false;
for(PageTab pageTab:pageList) {
if(pageTab.getKey().equals(key)) {
return true;
}
}
return false;
}
private class PageTab implements PortfolioStructureRef {
private final Long pageKey;
private final String title;
public PageTab(Long pageKey, String title) {
this.pageKey = pageKey;
this.title = title;
}
@Override
public Long getKey() {
return pageKey;
}
public String getTitle() {
return title;
}
}
}