/*
* 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;
import com.google.gwt.user.client.ui.HasWidgets;
import org.jboss.errai.common.client.dom.HTMLElement;
import org.uberfire.client.mvp.PerspectiveActivity;
import org.uberfire.client.mvp.PlaceManager;
import org.uberfire.client.mvp.UIPart;
import org.uberfire.client.workbench.events.SelectPlaceEvent;
import org.uberfire.client.workbench.panels.WorkbenchPanelPresenter;
import org.uberfire.client.workbench.panels.WorkbenchPanelView;
import org.uberfire.mvp.PlaceRequest;
import org.uberfire.workbench.model.PanelDefinition;
import org.uberfire.workbench.model.PartDefinition;
import org.uberfire.workbench.model.Position;
import org.uberfire.workbench.model.menu.Menus;
/**
* Internal framework component that handles the creation, destruction, layout, and composition (parent-child nesting)
* of all panels that make up a perspective. Also orchestrates adding and removing parts to/from panels. The outer most
* workbench panels (header, footer, perspective container) are managed by the
* {@link org.uberfire.client.workbench.WorkbenchLayout}.
* <p>
* <b>Application code should not invoke any of the methods of this class directly.</b> Doing so will corrupt the state
* of the PlaceManager, ActivityManager, and potentially other stateful framework components. Applications should always
* initiate Workbench actions through the public methods on {@link PlaceManager}.
*/
public interface PanelManager {
/**
* Returns the description of the entire panel + part tree that makes up the UI in its current state.
*/
PanelDefinition getRoot();
/**
* Adds the given part to the given panel, which must already be part of the visible workbench layout. Fires a
* {@link SelectPlaceEvent} with the given {@link PlaceRequest} once the part has been added.
* @param place The PlaceRequest that the part was resolved from. Not null.
* @param part The description of the part to add. Not null.
* @param panel definition of the panel to add the part to (must describe a panel that is already present in the
* layout). Not null.
* @param menus The menus to display for the given part. Null means no menus.
* @param uiPart The part's title and physical view. Not null.
* @param contextId part of a removed framework feature (TODO: remove this?)
* @param minInitialWidth minimum pixel width of the part's activity, or null if there is no known minimum width. The target
* panel will expand to the this width if the panel is not already at least as wide, and only if it
* supports resizing on the horizontal axis.
* @param minInitialHeight minimum pixel height of the part's activity, or null if there is no known minimum height. The target
* panel will expand to this height if the panel is not already at least as tall, and only if it supports
* resizing on the vertical axis.
*/
void addWorkbenchPart(final PlaceRequest place,
final PartDefinition part,
final PanelDefinition panel,
final Menus menus,
final UIPart uiPart,
final String contextId,
final Integer minInitialWidth,
final Integer minInitialHeight);
/**
* Adds an empty child panel of the target panel's default child type at the given position within the target panel.
* The new child panel will have the given dimensions and minimum sizes set on it.
* <p>
* TODO: the usefulness of this method to callers is questionable (versus creating a new child panel definition and
* calling {@link #addWorkbenchPanel(PanelDefinition, PanelDefinition, Position)}). candidate for deletion.
*/
PanelDefinition addWorkbenchPanel(final PanelDefinition targetPanel,
final Position position,
final Integer height,
final Integer width,
final Integer minHeight,
final Integer minWidth);
/**
* Adds the given child panel to the given target panel at the given position within the target. Upon successful
* completion of this method, the child panel will have a new parent panel. Its {@link PanelDefinition},
* {@link WorkbenchPanelPresenter}, and {@link WorkbenchPanelView} and those of its new parent will be updated to
* reflect the new relationship. Note that the given target panel will not necessarily be the new parent: panel
* implementations may choose to avoid collisions (more than one child panel in the same position) by redirecting
* requests to add children.
* @throws IllegalStateException if {@code targetPanel} already has a child at {@code position} and it doesn't have any special
* collision avoidance logic
* @throws UnsupportedOperationException if {@code targetPanel} doesn't support child panels.
* @throws IllegalArgumentException if {@code targetPanel} doesn't understand the given {@code position} value.
*/
PanelDefinition addWorkbenchPanel(final PanelDefinition targetPanel,
final PanelDefinition childPanel,
final Position position);
/**
* Creates an UberFire panel and installs its view in the given widget container.
* <p>
* <h3>Custom Panel Lifecycle</h3>
* <p>
* Custom panels can be disposed like any other panel: by calling {@link #removeWorkbenchPanel(PanelDefinition)}.
* Additionally, custom panels are monitored for DOM detachment. When a custom panel's view is removed from the DOM
* (whether directly removed from its parent or some ancestor is removed,) all the panel's parts are closed and then
* the associated panel is disposed.
* @param container the widget container to install the new panel in. The new panel will fill the container.
* @return the definition for the newly constructed panel. Never null. The panel's type will be {@code panelType};
* its parent will be null; {@code isRoot()} will return false.
*/
PanelDefinition addCustomPanel(HasWidgets container,
String panelType);
/**
* Creates an UberFire panel and installs its view in the given html element container.
* <p>
* <h3>Custom Panel Lifecycle</h3>
* <p>
* Custom panels can be disposed like any other panel: by calling {@link #removeWorkbenchPanel(PanelDefinition)}.
* Additionally, custom panels are monitored for DOM detachment. When a custom panel's view is removed from the DOM
* (whether directly removed from its parent or some ancestor is removed,) all the panel's parts are closed and then
* the associated panel is disposed.
* @param container the html element container to install the new panel in. The new panel will fill the container.
* @return the definition for the newly constructed panel. Never null. The panel's type will be {@code panelType};
* its parent will be null; {@code isRoot()} will return false.
*/
PanelDefinition addCustomPanel(HTMLElement container,
String panelType);
/**
* Removes the panel associated with the given definition, removing the panel's presenter and view from the
* workbench, and freeing any resources associated with them. The panel must have no parts and no child panels.
* @param toRemove the panel to remove from the workbench layout. Must not be null.
* @throws IllegalStateException if the panel contains parts or child panels
* @throws IllegalArgumentException if no panel presenter is currently associated with the given definition
*/
void removeWorkbenchPanel(final PanelDefinition toRemove) throws IllegalStateException;
/**
* Removes the part associated with the given PlaceRequest from the panel that contains it. If this operation
* removes the last part from the panel, and the panel is not the root panel, it will be removed from the workbench
* layout. Child panels are preserved by reparenting them to the removed panel's parent. Application code should not
* call this method directly; it is called by PlaceManager as part of the overall procedure in closing a place.
* @param toRemove the place that is closing. Must not be null.
* @return true if the associated part was found and removed; false if no matching part could be found.
*/
boolean removePartForPlace(final PlaceRequest toRemove);
void onPartFocus(final PartDefinition part);
void onPartLostFocus();
/**
* Gives focus to the given panel, if it is known to this PanelManager. Also removes focus from all other panels
* associated with this PanelManager.
* @param panel the panel to give focus to. May be null, in which case all panels will lose focus.
*/
void onPanelFocus(final PanelDefinition panel);
/**
* Closes the given part. This is a convenience method for <tt>placeManager.closePlace(part.getPlace())</tt>.
* @param part the part to close (remove from the GUI). Must not be null.
*/
void closePart(final PartDefinition part);
/**
* Clears all existing panel structure from the user interface, then installs a new root panel according to the
* specifications in the given {@link PanelDefinition}. Only installs the root panel; does not build the child
* panel/part structure recursively.
* @param root description of the new root panel to install. Must not be null.
*/
void setRoot(PerspectiveActivity activity,
PanelDefinition root);
/**
* Returns the first PanelDefinition whose place matches the given one.
* @return the definition for the panel servicing the given place, or null if no such part can be found.
*/
PanelDefinition getPanelForPlace(PlaceRequest place);
/**
* @param part that has been hidden
*/
void onPartHidden(PartDefinition part);
/**
* @param part the part that has been maximized
*/
void onPartMaximized(PartDefinition part);
/**
* @param part the part that has been minimized
*/
void onPartMinimized(PartDefinition part);
}