Java tutorial
/******************************************************************************* * Copyright 2009, 2010 Lars Grammel * * 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. *******************************************************************************/ package org.thechiselgroup.choosel.core.client.visualization; import org.thechiselgroup.choosel.core.client.error_handling.ErrorHandler; import org.thechiselgroup.choosel.core.client.persistence.Memento; import org.thechiselgroup.choosel.core.client.persistence.Persistable; import org.thechiselgroup.choosel.core.client.persistence.PersistableRestorationService; import org.thechiselgroup.choosel.core.client.resources.ResourceByPropertyMultiCategorizer; import org.thechiselgroup.choosel.core.client.resources.ResourceByUriMultiCategorizer; import org.thechiselgroup.choosel.core.client.resources.ResourceMultiCategorizer; import org.thechiselgroup.choosel.core.client.resources.persistence.ResourceSetAccessor; import org.thechiselgroup.choosel.core.client.resources.persistence.ResourceSetCollector; import org.thechiselgroup.choosel.core.client.ui.ImageButton; import org.thechiselgroup.choosel.core.client.ui.Presenter; import org.thechiselgroup.choosel.core.client.ui.SidePanelSection; import org.thechiselgroup.choosel.core.client.util.DisposeUtil; import org.thechiselgroup.choosel.core.client.util.NoSuchAdapterException; import org.thechiselgroup.choosel.core.client.util.collections.LightweightCollection; import org.thechiselgroup.choosel.core.client.visualization.model.ViewContentDisplay; import org.thechiselgroup.choosel.core.client.visualization.model.VisualizationModel; import org.thechiselgroup.choosel.core.client.visualization.model.extensions.ResourceModel; import org.thechiselgroup.choosel.core.client.visualization.model.extensions.SelectionModel; import org.thechiselgroup.choosel.core.client.visualization.model.managed.ManagedSlotMappingConfiguration; import org.thechiselgroup.choosel.core.client.visualization.model.persistence.ManagedSlotMappingConfigurationPersistence; import org.thechiselgroup.choosel.core.client.visualization.ui.VisualMappingsControl; import org.thechiselgroup.choosel.core.shared.util.ForTest; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.DockPanel; import com.google.gwt.user.client.ui.HasAlignment; import com.google.gwt.user.client.ui.StackPanel; import com.google.gwt.user.client.ui.Widget; public class DefaultView implements View { private class ViewPanel extends DockPanel implements ViewProvider { /** * Enables finding this view by searching the widget hierarchy. */ @Override public View get() { return DefaultView.this; } @Override protected void onDetach() { dispose(); super.onDetach(); } /* * Fixes bug that map is not resized if window is resized */ @Override public void setPixelSize(int width, int height) { DefaultView.this.setSize(width, height); super.setPixelSize(width, height); } } private static final String MEMENTO_LABEL_KEY = "label"; private static final String CSS_EXPANDER = "DefaultView-Expander"; private static final String CSS_CONFIGURATION_PANEL = "DefaultView-ConfigurationPanel"; private static final String CSS_VIEW_CONFIGURATION_PANEL = "view-configurationPanel"; // TODO rename private DockPanel configurationBar; // TODO rename private StackPanel sideBar; /** * The main panel of this view. It contains all other widgets of this view. */ private ViewPanel viewPanel; private Presenter resourceModelPresenter; private Presenter selectionModelPresenter; private int width; private int height; /** * Sections that will be displayed in the side panel. This is a lightweight * collections so we can check whether it is empty or not. */ private LightweightCollection<SidePanelSection> sidePanelSections; private ViewContentDisplay contentDisplay; private VisualizationModel visualizationModel; private ResourceModel resourceModel; private SelectionModel selectionModel; private boolean isInitialized; private String contentType; private ErrorHandler errorHandler; private String label; private ManagedSlotMappingConfigurationPersistence managedSlotMappingConfigurationPersistence; private ManagedSlotMappingConfiguration managedSlotMappingConfiguration; private static final String MEMENTO_CONTENT_DISPLAY = "content-display"; private static final String MEMENTO_RESOURCE_MODEL = "resource-model"; private static final String MEMENTO_SELECTION_MODEL = "selection-model"; private static final String MEMENTO_SLOT_MAPPINGS = "slot-mappings"; private static final String MEMENTO_GROUPING = "grouping"; // TODO change parameter order in constructor // TODO change contentDisplay to more restricted interface public DefaultView(ViewContentDisplay contentDisplay, String label, String contentType, Presenter selectionModelPresenter, Presenter resourceModelPresenter, VisualMappingsControl visualMappingsControl, LightweightCollection<SidePanelSection> sidePanelSections, VisualizationModel visualizationModel, ResourceModel resourceModel, SelectionModel selectionModel, ManagedSlotMappingConfiguration managedSlotMappingConfiguration, ManagedSlotMappingConfigurationPersistence managedSlotMappingConfigurationPersistence, ErrorHandler errorHandler) { assert label != null; assert contentType != null; assert contentDisplay != null; assert selectionModelPresenter != null; assert resourceModelPresenter != null; assert sidePanelSections != null; assert visualizationModel != null; assert resourceModel != null; assert selectionModel != null; assert managedSlotMappingConfiguration != null; assert managedSlotMappingConfigurationPersistence != null; assert errorHandler != null; this.label = label; this.contentType = contentType; this.contentDisplay = contentDisplay; this.selectionModelPresenter = selectionModelPresenter; this.resourceModelPresenter = resourceModelPresenter; this.sidePanelSections = sidePanelSections; this.visualizationModel = visualizationModel; this.selectionModel = selectionModel; this.resourceModel = resourceModel; this.managedSlotMappingConfiguration = managedSlotMappingConfiguration; this.managedSlotMappingConfigurationPersistence = managedSlotMappingConfigurationPersistence; this.errorHandler = errorHandler; } @Override public <T> T adaptTo(Class<T> clazz) throws NoSuchAdapterException { return contentDisplay.adaptTo(clazz); } @Override public Widget asWidget() { return viewPanel; } @Override public void dispose() { resourceModelPresenter = DisposeUtil.safelyDispose(resourceModelPresenter, errorHandler); selectionModelPresenter = DisposeUtil.safelyDispose(selectionModelPresenter, errorHandler); visualizationModel = DisposeUtil.safelyDispose(visualizationModel, errorHandler); } @ForTest protected void doRestore(Memento state, PersistableRestorationService restorationService, ResourceSetAccessor accessor) { assert isInitialized : "view has to be initialized before restoring it"; contentDisplay.startRestore(); // restoreGrouping(state.getChild(MEMENTO_GROUPING)); restoreGrouping(state.getChild(MEMENTO_GROUPING)); restore(resourceModel, state, MEMENTO_RESOURCE_MODEL, restorationService, accessor); restore(selectionModel, state, MEMENTO_SELECTION_MODEL, restorationService, accessor); contentDisplay.restore(state.getChild(MEMENTO_CONTENT_DISPLAY), restorationService, accessor); managedSlotMappingConfigurationPersistence.restore(managedSlotMappingConfiguration, state.getChild(MEMENTO_SLOT_MAPPINGS)); setLabel((String) state.getValue(MEMENTO_LABEL_KEY)); contentDisplay.endRestore(); } @Override public String getContentType() { return contentType; } @Override public String getLabel() { return label; } @Override public VisualizationModel getModel() { assert visualizationModel != null : "view has been disposed"; return visualizationModel; } protected String getModuleBase() { return GWT.getModuleBaseURL(); } @Override public ResourceModel getResourceModel() { return resourceModel; } @Override public SelectionModel getSelectionModel() { return selectionModel; } @Override public void init() { assert !isInitialized : "view has already been initialized"; resourceModelPresenter.init(); initUI(); isInitialized = true; } private void initConfigurationPanelUI() { configurationBar = new DockPanel(); configurationBar.setSize("100%", ""); configurationBar.setStyleName(CSS_VIEW_CONFIGURATION_PANEL); initResourceModelPresenter(); initSideBarExpander(); initSelectionModelPresenter(); } private void initResourceModelPresenter() { Widget widget = resourceModelPresenter.asWidget(); configurationBar.add(widget, DockPanel.WEST); configurationBar.setCellHorizontalAlignment(widget, HasAlignment.ALIGN_LEFT); } private void initSelectionModelPresenter() { selectionModelPresenter.init(); Widget widget = selectionModelPresenter.asWidget(); configurationBar.add(widget, DockPanel.EAST); configurationBar.setCellHorizontalAlignment(widget, HasAlignment.ALIGN_RIGHT); configurationBar.setCellWidth(widget, "100%"); // eats up all space } private void initSideBar() { assert sideBar == null; assert sidePanelSections != null; sideBar = new StackPanel(); sideBar.setStyleName(CSS_CONFIGURATION_PANEL); sideBar.setVisible(false); for (SidePanelSection sidePanelSection : sidePanelSections) { sideBar.add(sidePanelSection.getWidget(), sidePanelSection.getSectionTitle()); } } private void initSideBarExpander() { ImageButton expander = ImageButton.createExpanderButton(); expander.setStyleName(CSS_EXPANDER); expander.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { sideBar.setVisible(!sideBar.isVisible()); updateContentDisplaySize(); } }); configurationBar.add(expander, DockPanel.EAST); configurationBar.setCellHorizontalAlignment(expander, HasAlignment.ALIGN_RIGHT); } protected void initUI() { initConfigurationPanelUI(); initSideBar(); viewPanel = new ViewPanel(); viewPanel.setBorderWidth(0); viewPanel.setSpacing(0); viewPanel.setSize("500px", "300px"); viewPanel.add(configurationBar, DockPanel.NORTH); viewPanel.add(contentDisplay.asWidget(), DockPanel.CENTER); viewPanel.add(sideBar, DockPanel.EAST); viewPanel.setCellHeight(contentDisplay.asWidget(), "100%"); } @Override public boolean isAdaptableTo(Class<?> clazz) { return contentDisplay.isAdaptableTo(clazz); } // XXX remove once content display lifecycle working public boolean isReady() { return contentDisplay.isReady(); } @Override public void restore(final Memento state, final PersistableRestorationService restorationService, final ResourceSetAccessor accessor) { /* * wait for content to be ready (needed for graph view swf loading on * restore) */ // XXX this might be the cause for issue 25 // TODO introduce proper view content display lifecycle instead if (contentDisplay.isReady()) { doRestore(state, restorationService, accessor); } else { new Timer() { @Override public void run() { restore(state, restorationService, accessor); } }.schedule(200); } } private void restore(Object target, Memento parentMemento, String targetMementoKey, PersistableRestorationService restorationService, ResourceSetAccessor accessor) { if (target instanceof Persistable) { ((Persistable) target).restore(parentMemento.getChild(targetMementoKey), restorationService, accessor); } } // TODO extract constants private void restoreGrouping(Memento groupingMemento) { assert groupingMemento != null; String categorizerType = (String) groupingMemento.getValue("type"); if ("byProperty".equals(categorizerType)) { String property = (String) groupingMemento.getValue("property"); visualizationModel.setCategorizer(new ResourceByPropertyMultiCategorizer(property)); } else if ("byUri".equals(categorizerType)) { visualizationModel.setCategorizer(new ResourceByUriMultiCategorizer()); } } private void save(Object target, Memento parentMemento, String targetMementoKey, ResourceSetCollector resourceSetCollector) { if (target instanceof Persistable) { parentMemento.addChild(targetMementoKey, ((Persistable) target).save(resourceSetCollector)); } } @Override public Memento save(ResourceSetCollector resourceSetCollector) { Memento memento = new Memento(); saveGrouping(memento); save(selectionModel, memento, MEMENTO_SELECTION_MODEL, resourceSetCollector); save(resourceModel, memento, MEMENTO_RESOURCE_MODEL, resourceSetCollector); memento.addChild(MEMENTO_CONTENT_DISPLAY, contentDisplay.save(resourceSetCollector)); memento.addChild(MEMENTO_SLOT_MAPPINGS, managedSlotMappingConfigurationPersistence.save(managedSlotMappingConfiguration)); memento.setValue(MEMENTO_LABEL_KEY, getLabel()); return memento; } // TODO extract constants private void saveGrouping(Memento memento) { Memento groupingMemento = new Memento(); ResourceMultiCategorizer categorizer = visualizationModel.getCategorizer(); if (categorizer instanceof ResourceByPropertyMultiCategorizer) { groupingMemento.setValue("type", "byProperty"); groupingMemento.setValue("property", ((ResourceByPropertyMultiCategorizer) categorizer).getProperty()); } else if (categorizer instanceof ResourceByUriMultiCategorizer) { groupingMemento.setValue("type", "byUri"); } memento.addChild(MEMENTO_GROUPING, groupingMemento); } @Override public void setLabel(String label) { this.label = label; } /** * Sets the size of the default view, not including decorations such as * border, margin, and padding (and thus different from offset width and * height). * * @param width * width in pixels * @param height * height in pixels */ private void setSize(int width, int height) { assert height >= 0; assert width >= 0; this.width = width; this.height = height; updateContentDisplaySize(); } private void updateContentDisplaySize() { /* * special resize method required, because otherwise window height * cannot be reduced by dragging - see * http://code.google.com/p/google-web-toolkit/issues/detail?id=316 */ int targetHeight = height - configurationBar.getOffsetHeight(); int targetWidth = sideBar.isVisible() ? width - sideBar.getOffsetWidth() : width; contentDisplay.setSize(targetWidth, targetHeight); } }