package com.constellio.app.ui.pages.home; import static com.constellio.app.ui.i18n.i18n.$; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.vaadin.peter.contextmenu.ContextMenu; import org.vaadin.peter.contextmenu.ContextMenu.ContextMenuOpenedOnTableFooterEvent; import org.vaadin.peter.contextmenu.ContextMenu.ContextMenuOpenedOnTableHeaderEvent; import org.vaadin.peter.contextmenu.ContextMenu.ContextMenuOpenedOnTableRowEvent; import com.constellio.app.entities.navigation.PageItem; import com.constellio.app.entities.navigation.PageItem.CustomItem; import com.constellio.app.entities.navigation.PageItem.RecentItemTable; import com.constellio.app.entities.navigation.PageItem.RecentItemTable.RecentItem; import com.constellio.app.entities.navigation.PageItem.RecordTable; import com.constellio.app.entities.navigation.PageItem.RecordTree; import com.constellio.app.modules.rm.ui.components.tree.RMTreeDropHandlerImpl; import com.constellio.app.services.factories.ConstellioFactories; import com.constellio.app.ui.application.ConstellioUI; import com.constellio.app.ui.entities.MetadataVO; import com.constellio.app.ui.entities.RecordVO; import com.constellio.app.ui.framework.components.contextmenu.BaseContextMenuTableListener; import com.constellio.app.ui.framework.components.contextmenu.RecordContextMenu; import com.constellio.app.ui.framework.components.contextmenu.RecordContextMenuHandler; import com.constellio.app.ui.framework.components.converters.JodaDateTimeToStringConverter; import com.constellio.app.ui.framework.components.menuBar.RecordMenuBarHandler; import com.constellio.app.ui.framework.components.table.BaseTable; import com.constellio.app.ui.framework.components.table.RecordVOSelectionTableAdapter; import com.constellio.app.ui.framework.components.table.RecordVOTable; import com.constellio.app.ui.framework.components.tree.RecordLazyTree; import com.constellio.app.ui.framework.components.tree.RecordLazyTreeTabSheet; import com.constellio.app.ui.framework.containers.RecordVOLazyContainer; import com.constellio.app.ui.framework.data.RecordLazyTreeDataProvider; import com.constellio.app.ui.framework.data.RecordVODataProvider; import com.constellio.app.ui.framework.decorators.contextmenu.ContextMenuDecorator; import com.constellio.app.ui.framework.items.RecordVOItem; import com.constellio.app.ui.pages.base.BaseViewImpl; import com.constellio.app.ui.params.ParamUtils; import com.constellio.app.ui.util.FileIconUtils; import com.constellio.model.entities.schemas.Schemas; import com.constellio.model.services.factories.ModelLayerFactory; import com.vaadin.data.Property; import com.vaadin.data.util.BeanItem; import com.vaadin.data.util.BeanItemContainer; import com.vaadin.data.util.ObjectProperty; import com.vaadin.event.ItemClickEvent; import com.vaadin.event.ItemClickEvent.ItemClickListener; import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent; import com.vaadin.server.Page; import com.vaadin.shared.MouseEventDetails.MouseButton; import com.vaadin.ui.Component; import com.vaadin.ui.CustomComponent; import com.vaadin.ui.Label; import com.vaadin.ui.MenuBar; import com.vaadin.ui.TabSheet; import com.vaadin.ui.TabSheet.Tab; import com.vaadin.ui.Table; import com.vaadin.ui.Tree.TreeDragMode; public class HomeViewImpl extends BaseViewImpl implements HomeView { private final HomePresenter presenter; private List<PageItem> tabs; private TabSheet tabSheet; private List<ContextMenuDecorator> contextMenuDecorators = new ArrayList<>(); public HomeViewImpl() { presenter = new HomePresenter(this); } @Override protected void initBeforeCreateComponents(ViewChangeEvent event) { tabs = presenter.forParams(event.getParameters()).getTabs(); } @Override protected String getTitle() { return $("HomeView.viewTitle"); } @Override protected boolean isFullWidthIfActionMenuAbsent() { return true; } @Override protected Component buildMainComponent(ViewChangeEvent event) { tabSheet = new TabSheet(); tabSheet.addStyleName("records-management"); Map<String, Tab> tabsByCode = new HashMap<>(); for (PageItem item : tabs) { Tab tab = tabSheet.addTab(new PlaceHolder(), $("HomeView.tab." + item.getCode())); tabsByCode.put(item.getCode(), tab); } tabSheet.addSelectedTabChangeListener(new TabSheet.SelectedTabChangeListener() { @Override public void selectedTabChange(TabSheet.SelectedTabChangeEvent event) { Tab currentTab = tabSheet.getTab(tabSheet.getSelectedTab()); selectTab(currentTab); } }); selectTab(tabsByCode.get(presenter.getCurrentTab())); return tabSheet; } @Override public String getSelectedTabCode() { return presenter.getCurrentTab(); } private void selectTab(Tab tab) { if (tab == null) { return; } int position = tabSheet.getTabPosition(tab); PageItem item = tabs.get(position); presenter.tabSelected(item.getCode()); tabSheet.setSelectedTab(position); PlaceHolder tabComponent = (PlaceHolder) tab.getComponent(); if (tabComponent.getComponentCount() == 0) { tabComponent.setCompositionRoot(buildComponentFor(tab)); } ParamUtils.setParams(item.getCode()); } private Component buildComponentFor(Tab tab) { int indexOfSelectedTab = tabSheet.getTabPosition(tab); PageItem tabSource = tabs.get(indexOfSelectedTab); switch (tabSource.getType()) { case RECENT_ITEM_TABLE: return buildRecentItemTable((RecentItemTable) tabSource); case RECORD_TABLE: return buildRecordTable((RecordTable) tabSource); case RECORD_TREE: return buildRecordTreeOrRecordMultiTree((RecordTree) tabSource); case CUSTOM_ITEM: return buildCustomComponent((CustomItem) tabSource); default: throw new RuntimeException("Unsupported tab type : " + tabSource.getType()); } } private Component buildRecentItemTable(RecentItemTable recentItems) { String tableId = "HomeView." + recentItems.getCode(); final RecentTable recentTable = new RecentTable(tableId, recentItems.getItems(getConstellioFactories().getAppLayerFactory(), getSessionContext())); recentTable.setSizeFull(); recentTable.addStyleName("record-table"); return new RecordVOSelectionTableAdapter(recentTable) { @Override public void selectAll() { selectAllByItemId(); } @Override public void deselectAll() { deselectAllByItemId(); } @Override public boolean isAllItemsSelected() { return isAllItemsSelectedByItemId(); } @Override public boolean isAllItemsDeselected() { return isAllItemsDeselectedByItemId(); } @Override public void setSelected(Object itemId, boolean selected) { RecordVO recordVO = recentTable.getRecordVO(itemId); String recordId = recordVO.getId(); presenter.selectionChanged(recordId, selected); adjustSelectAllButton(selected); } @Override public boolean isSelected(Object itemId) { RecordVO recordVO = recentTable.getRecordVO(itemId); String recordId = recordVO.getId(); return presenter.isSelected(recordId); } }; } private Component buildRecordTable(final RecordTable recordTable) { RecordVODataProvider dataProvider = recordTable.getDataProvider(getConstellioFactories().getAppLayerFactory(), getSessionContext()); RecordVOLazyContainer container = new RecordVOLazyContainer(dataProvider); final RecordVOTable table = new RecordVOTable(container); table.addStyleName("record-table"); table.setSizeFull(); for (Object item : table.getContainerPropertyIds()) { if (item instanceof MetadataVO) { MetadataVO property = (MetadataVO) item; if (property.getCode() != null && property.getCode().contains(Schemas.MODIFIED_ON.getLocalCode())) { table.setColumnWidth(property, 180); } } } table.addItemClickListener(new ItemClickListener() { @Override public void itemClick(ItemClickEvent event) { if (event.getButton() == MouseButton.LEFT) { RecordVOItem recordItem = (RecordVOItem) event.getItem(); RecordVO recordVO = recordItem.getRecord(); presenter.recordClicked(recordVO.getId(), null); } } }); return new RecordVOSelectionTableAdapter(table) { @Override public void selectAll() { selectAllByItemId(); } @Override public void deselectAll() { deselectAllByItemId(); } @Override public boolean isAllItemsSelected() { return isAllItemsSelectedByItemId(); } @Override public boolean isAllItemsDeselected() { return isAllItemsDeselectedByItemId(); } @Override public boolean isSelected(Object itemId) { RecordVOItem item = (RecordVOItem) table.getItem(itemId); String recordId = item.getRecord().getId(); return presenter.isSelected(recordId); } @Override public void setSelected(Object itemId, boolean selected) { RecordVOItem item = (RecordVOItem) table.getItem(itemId); String recordId = item.getRecord().getId(); presenter.selectionChanged(recordId, selected); adjustSelectAllButton(selected); } }; } private Component buildRecordTreeOrRecordMultiTree(RecordTree recordTree) { List<RecordLazyTreeDataProvider> providers = recordTree.getDataProviders( getConstellioFactories().getAppLayerFactory(), getSessionContext()); return providers.size() > 1 ? buildRecordMultiTree(recordTree, providers) : buildRecordTree(recordTree, providers.get(0)); } private RecordLazyTreeTabSheet buildRecordMultiTree(final RecordTree recordTree, List<RecordLazyTreeDataProvider> providers) { final RecordLazyTreeTabSheet subTabSheet = new RecordLazyTreeTabSheet(providers) { @Override protected RecordLazyTree newLazyTree(RecordLazyTreeDataProvider dataProvider, int bufferSize) { return buildRecordTree(recordTree, dataProvider); } }; subTabSheet.setSelectedTab(recordTree.getDefaultDataProvider()); return subTabSheet; } private static int getBufferSizeFromConfig() { ConstellioFactories constellioFactories = ConstellioFactories.getInstance(); ModelLayerFactory modelLayerFactory = constellioFactories.getModelLayerFactory(); return modelLayerFactory.getSystemConfigs().getLazyTreeBufferSize(); } private RecordLazyTree buildRecordTree(RecordTree recordTree, final RecordLazyTreeDataProvider provider) { RecordLazyTree tree = new RecordLazyTree(provider, getBufferSizeFromConfig()); tree.addItemClickListener(new ItemClickListener() { @Override public void itemClick(ItemClickEvent event) { if (event.getButton() == MouseButton.LEFT) { String recordId = (String) event.getItemId(); presenter.recordClicked(recordId, provider.getTaxonomyCode()); } } }); ContextMenu menu = recordTree.getContextMenu(); for (ContextMenuDecorator contextMenuDecorator : contextMenuDecorators) { menu = contextMenuDecorator.decorate(this, menu); } if (menu != null) { menu.setAsTreeContextMenu(tree.getNestedTree()); } tree.getNestedTree().setDragMode(TreeDragMode.NODE); tree.getNestedTree().setDropHandler(new RMTreeDropHandlerImpl() { @Override public void showErrorMessage(String errorMessage) { HomeViewImpl.this.showErrorMessage(errorMessage); } }); tree.loadAndExpand(recordTree.getExpandedRecordIds()); return tree; } private Component buildCustomComponent(CustomItem tabSource) { Component component = tabSource.buildCustomComponent(getConstellioFactories(), getSessionContext()); if (component instanceof BaseViewImpl) { ((BaseViewImpl) component).enter(null); } component.setSizeFull(); return component; } public void addContextMenuDecorator(ContextMenuDecorator decorator) { this.contextMenuDecorators.add(decorator); } public List<ContextMenuDecorator> getContextMenuDecorators() { return this.contextMenuDecorators; } public void removeContextMenuDecorator(ContextMenuDecorator decorator) { this.contextMenuDecorators.remove(decorator); } private static class PlaceHolder extends CustomComponent { @Override public void setCompositionRoot(Component compositionRoot) { super.setCompositionRoot(compositionRoot); } @Override public Component getCompositionRoot() { return super.getCompositionRoot(); } } private class RecentTable extends BaseTable { private static final String MENUBAR_PROPERTY_ID = "menuBar"; @SuppressWarnings({ "rawtypes", "unchecked" }) public RecentTable(String tableId, List<RecentItem> recentItems) { super(tableId); BeanItemContainer container = new BeanItemContainer<>(RecentItem.class, recentItems); setContainerDataSource(container); addStyleName(RecordVOTable.CLICKABLE_ROW_STYLE_NAME); setVisibleColumns(RecentItem.CAPTION, RecentItem.LAST_ACCESS); setColumnHeader(RecentItem.CAPTION, $("HomeView.recentItem.caption")); setColumnHeader(RecentItem.LAST_ACCESS, $("HomeView.recentItem.lastAccess")); setColumnExpandRatio(RecentItem.CAPTION, 1); addItemClickListener(new ItemClickListener() { @Override public void itemClick(ItemClickEvent event) { if (event.getButton() == MouseButton.LEFT) { BeanItem<RecentItem> item = (BeanItem<RecentItem>) event.getItem(); presenter.recordClicked(item.getBean().getId(), null); } } }); setCellStyleGenerator(new CellStyleGenerator() { @Override public String getStyle(Table source, Object itemId, Object propertyId) { if (RecentItem.CAPTION.equals(propertyId)) { RecordVO recordVO = getRecordVO(itemId); try { String extension = FileIconUtils.getExtension(recordVO); if (extension != null) { return "file-icon-" + extension; } } catch (Exception e) { // Ignore the exception } } return null; } }); addContextMenuAndMenuBarColumn(recentItems); } @Override public Property<?> getContainerProperty(Object itemId, Object propertyId) { if (RecentItem.LAST_ACCESS.equals(propertyId)) { RecentItem recentItem = (RecentItem) itemId; String value = new JodaDateTimeToStringConverter() .convertToPresentation(recentItem.getLastAccess(), String.class, getSessionContext().getCurrentLocale()); return new ObjectProperty<>(value); } return super.getContainerProperty(itemId, propertyId); } @SuppressWarnings("unchecked") private RecordVO getRecordVO(Object itemId) { BeanItem<RecentItem> recordVOItem = (BeanItem<RecentItem>) getItem(itemId); RecordVO recordVO = recordVOItem.getBean().getRecord(); return recordVO; } protected void addContextMenuAndMenuBarColumn(List<RecentItem> recentItems) { boolean menuBarColumnGenerated = getColumnGenerator(MENUBAR_PROPERTY_ID) != null; if (!menuBarColumnGenerated) { boolean menuBarRequired = false; String schemaCode = null; for (RecentItem recentItem : recentItems) { schemaCode = recentItem.getRecord().getSchema().getCode(); List<RecordMenuBarHandler> recordMenuBarHandlers = ConstellioUI.getCurrent().getRecordMenuBarHandlers(); for (RecordMenuBarHandler recordMenuBarHandler : recordMenuBarHandlers) { if (recordMenuBarHandler.isMenuBarForSchemaCode(schemaCode)) { menuBarRequired = true; break; } } } if (menuBarRequired) { RecordContextMenu contextMenu = null; List<RecordContextMenuHandler> recordContextMenuHandlers = ConstellioUI.getCurrent().getRecordContextMenuHandlers(); for (RecordContextMenuHandler recordContextMenuHandler : recordContextMenuHandlers) { if (recordContextMenuHandler.isContextMenuForSchemaCode(schemaCode)) { contextMenu = recordContextMenuHandler.getForSchemaCode(schemaCode); break; } } if (contextMenu != null) { contextMenu.setAsContextMenuOf(this); final RecordContextMenu finalContextMenu = contextMenu; BaseContextMenuTableListener contextMenuTableListener = new BaseContextMenuTableListener() { @Override public void onContextMenuOpenFromFooter(ContextMenuOpenedOnTableFooterEvent event) { } @Override public void onContextMenuOpenFromHeader(ContextMenuOpenedOnTableHeaderEvent event) { } @Override public void onContextMenuOpenFromRow(ContextMenuOpenedOnTableRowEvent event) { Object itemId = event.getItemId(); RecordVO recordVO = getRecordVO(itemId); finalContextMenu.openFor(recordVO); } }; contextMenu.addContextMenuTableListener(contextMenuTableListener); } addGeneratedColumn(MENUBAR_PROPERTY_ID, new ColumnGenerator() { @Override public Object generateCell(Table source, Object itemId, Object columnId) { RecordVO recordVO = getRecordVO(itemId); MenuBar menuBar = null; List<RecordMenuBarHandler> recordMenuBarHandlers = ConstellioUI.getCurrent().getRecordMenuBarHandlers(); for (RecordMenuBarHandler recordMenuBarHandler : recordMenuBarHandlers) { menuBar = recordMenuBarHandler.get(recordVO); if (menuBar != null) { break; } } return menuBar != null ? menuBar : new Label(""); } }); setColumnHeader(MENUBAR_PROPERTY_ID, ""); } } } } @Override public void openURL(String url) { Page.getCurrent().open(url, null); } }