/* * Copyright 2015 Red Hat, Inc. and/or its affiliates. * * 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.uberfire.client.workbench.panels.impl; import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import javax.annotation.PostConstruct; import com.google.gwt.user.client.ui.IsWidget; import org.uberfire.client.mvp.PerspectiveManager; import org.uberfire.client.workbench.panels.WorkbenchPanelPresenter; import org.uberfire.client.workbench.panels.WorkbenchPanelView; import org.uberfire.client.workbench.part.WorkbenchPartPresenter; import org.uberfire.client.workbench.pmgr.nswe.part.WorkbenchPartPresenterDefault; import org.uberfire.workbench.model.PanelDefinition; import org.uberfire.workbench.model.PartDefinition; import org.uberfire.workbench.model.Position; import static org.uberfire.debug.Debug.objectId; /** * Basic implementation of common functionality in a panel presenter. * <p> * At the least, concrete subclasses have to implement {@link #asPresenterType()} to return {@code this}. Subclasses may * override other methods as necessary to customize behaviour for use with specialized layouts and view implementations. */ public abstract class AbstractWorkbenchPanelPresenter<P extends AbstractWorkbenchPanelPresenter<P>> implements WorkbenchPanelPresenter { protected final PerspectiveManager perspectiveManager; protected final Map<Position, WorkbenchPanelPresenter> childPanels = new LinkedHashMap<Position, WorkbenchPanelPresenter>(); private final WorkbenchPanelView<P> view; private WorkbenchPanelPresenter parent; private PanelDefinition definition; public AbstractWorkbenchPanelPresenter(final WorkbenchPanelView<P> view, final PerspectiveManager perspectiveManager) { this.view = view; this.perspectiveManager = perspectiveManager; } /** * Returns a reference to {@code this}. Helps superclass code work around generic type checking problems. */ protected abstract P asPresenterType(); @PostConstruct void init() { getPanelView().init(this.asPresenterType()); } @Override public WorkbenchPanelPresenter getParent() { return parent; } @Override public void setParent(WorkbenchPanelPresenter parent) { this.parent = parent; } @Override public PanelDefinition getDefinition() { return definition; } @Override public void setDefinition(final PanelDefinition definition) { this.definition = definition; view.setElementId(definition.getElementId()); } /** * Most panel types are their own default child type, so this implementation returns {@code getClass().getName()}. * Subclasses can override if they prefer a different child type. */ @Override public String getDefaultChildType() { return getClass().getName(); } /** * Calls {@link #addPart(org.uberfire.client.workbench.part.WorkbenchPartPresenter, String)}. Subclasses can * take advantage of this by only overriding the 2-arg version. */ @Override public void addPart(final WorkbenchPartPresenter part) { addPart(part, null); } /** * Adds the given part to the view returned by {@link #getPanelView()}, ignoring the given {@code contextId}. * Subclasses that care about context id's will override this method. */ @Override public void addPart(final WorkbenchPartPresenter part, final String contextId) { // special case: when new perspectives are being built up based on definitions, // our definition will already say it contains the given part! We should not try to add it again. if (!definition.getParts().contains(part.getDefinition())) { definition.addPart(part.getDefinition()); } getPanelView().addPart(part.getPartView()); } @Override public boolean removePart(final PartDefinition part) { view.removePart(part); return definition.removePart(part); } /** * This base implementation should be sufficient for most panels. It modifies the panel definition and adds the * child view to this panel's view. In case the requested position is already in use for this panel, this method * will throw an {@link IllegalStateException}. Subclasses may override and implement some other collision avoidance * strategy. */ @Override public void addPanel(final WorkbenchPanelPresenter child, final Position position) { if (childPanels.containsKey(position)) { throw new IllegalStateException("This panel already has a " + position + " child"); } definition.insertChild(position, child.getDefinition()); getPanelView().addPanel(child.getDefinition(), child.getPanelView(), position); childPanels.put(position, child); child.setParent(this); } @Override public boolean removePanel(WorkbenchPanelPresenter child) { Position position = positionOf(child); if (position == null) { return false; } getPanelView().removePanel(child.getPanelView()); definition.removeChild(position); childPanels.remove(position); child.setParent(null); return true; } @Override public Map<Position, WorkbenchPanelPresenter> getPanels() { return Collections.unmodifiableMap(childPanels); } protected Position positionOf(WorkbenchPanelPresenter child) { for (Map.Entry<Position, WorkbenchPanelPresenter> entry : childPanels.entrySet()) { if (child == entry.getValue()) { return entry.getKey(); } } return null; } @Override public void changeTitle(final PartDefinition part, final String title, final IsWidget titleDecorator) { getPanelView().changeTitle(part, title, titleDecorator); } @Override public void setFocus(final boolean hasFocus) { view.setFocus(hasFocus); } @Override public boolean selectPart(final PartDefinition part) { if (!contains(part)) { return false; } view.selectPart(part); return true; } private boolean contains(final PartDefinition part) { return definition.getParts().contains(part); } @Override public void maximize() { view.maximize(); } @Override public void unmaximize() { view.unmaximize(); } @Override public WorkbenchPanelView<P> getPanelView() { return view; } @Override public void onResize(final int width, final int height) { if (width != 0) { getDefinition().setWidth(width); } if (height != 0) { getDefinition().setHeight(height); } } @Override public String toString() { StringBuilder sb = new StringBuilder(getClass().getName()); sb.append(objectId(this)); if (getDefinition() == null) { sb.append(" (no definition)"); } else { sb.append(" id=").append(getDefinition().getElementId()); } return sb.toString(); } public Class<? extends WorkbenchPartPresenter> getPartType() { return WorkbenchPartPresenterDefault.class; } }