/**
* Copyright (C) 2015 Valkyrie RCP
*
* 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.valkyriercp.application.docking;
import com.vldocking.swing.docking.*;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import javax.swing.*;
import java.awt.*;
import java.beans.PropertyChangeEvent;
/**
* Utility class for dealing with VLDocking.
*
* @author <a href = "mailto:julio.arguello@gmail.com" >Julio Arg??ello (JAF)</a>
*/
public final class VLDockingUtils {
/**
* The activation infix for <em>active</em> UI property names.
*/
private static final String ACTIVE_INFIX = ".active";
/**
* The '{@value #DOT}' character.
*/
private static final char DOT = '.';
/**
* The activation infix for <em>inactive</em> UI property names.
*/
private static final String INACTIVE_INFIX = ".inactive";
/**
* Utility classes should not have a public or default constructor.
*/
private VLDockingUtils() {
}
/**
* Fixes an VLDocking bug consisting on dockables that belong to a docking desktop have no state on it.
*
* @param dockable
* the dockable candidate.
* @return its dockable state. If none then registers the dockable again and ensures dockable state is not null.
*/
public static DockableState fixVLDockingBug(DockingDesktop dockingDesktop, Dockable dockable) {
Assert.notNull(dockingDesktop, "dockingDesktop");
Assert.notNull(dockable, "dockable");
final DockingContext dockingContext = dockingDesktop.getContext();
final DockKey dockKey = dockable.getDockKey();
DockableState dockableState = dockingDesktop.getDockableState(dockable);
final Boolean thisFixApplies = (dockingContext.getDockableByKey(dockKey.getKey()) != null);
if ((thisFixApplies) && (dockableState == null)) {
dockingDesktop.registerDockable(dockable);
dockableState = dockingDesktop.getDockableState(dockable);
// dockKey.setLocation(dockableState.getLocation());
Assert.notNull(dockableState, "dockableState");
}
return dockableState;
}
/**
* Transforms a UI object key into an activation aware key name.
*
* @param key
* the key.
* @param active
* <code>true</code> for <em>active</em> UI keys and <code>false</code> for inactive.
* @return the transformed key.
*/
public static String activationKey(String key, Boolean active) {
Assert.notNull(key, "key");
Assert.notNull(active, "active");
final int index = key.lastIndexOf(VLDockingUtils.DOT);
final String overlay = active ? VLDockingUtils.ACTIVE_INFIX : VLDockingUtils.INACTIVE_INFIX;
// return StringUtils.overlay(key, overlay, index, index);
return key; //TODO
}
/**
* Null safe version of {@link #findDockViewTitleBar(java.awt.Component)}.
*
* @param component
* the component.
* @return the dock view title bar.
*
* @see #findDockViewTitleBar(java.awt.Component)
*/
public static DockViewTitleBar nullSafeFindDockViewTitleBar(Component component) {
final DockViewTitleBar dockViewTitleBar;
if (component != null) {
dockViewTitleBar = VLDockingUtils.findDockViewTitleBar(component);
} else {
dockViewTitleBar = null;
}
return dockViewTitleBar;
}
/**
* Find the dock view title bar associated to the dockable container of a given component (if any).
*
* @param component
* the component.
* @return the dock view title bar.
*/
public static DockViewTitleBar findDockViewTitleBar(Component component) {
Assert.notNull(component, "component");
final SingleDockableContainer sdc = DockingUtilities.findSingleDockableContainerAncestor(component);
final DockViewTitleBar dockViewTitleBar;
if (sdc == null) {
dockViewTitleBar = null;
} else if (sdc instanceof DockView) {
dockViewTitleBar = ((DockView) sdc).getTitleBar();
} else if (sdc instanceof AutoHideExpandPanel) {
dockViewTitleBar = ((AutoHideExpandPanel) sdc).getTitleBar();
} else {
dockViewTitleBar = null;
}
return dockViewTitleBar;
}
/**
* A bean useful for dealing with focus changed events within VLDocking.
*
* @author <a href = "mailto:julio.arguello@gmail.com" >Julio Arg??ello (JAF)</a>
*/
public static class FocusGainedBean {
/**
* The number of instances, useful for debugging.
*/
private static int instanceCount = 0;
/**
* The target event.
*/
private PropertyChangeEvent event;
/**
* The last active title bar.
*/
private DockViewTitleBar lastTitleBar;
/**
* The description of what's happening.
*/
private String whatsHappening;
/**
* Default constructor: increase instance count.
*/
public FocusGainedBean() {
++FocusGainedBean.instanceCount;
}
/**
* Gets the target event.
*
* @return the event.
*/
public final PropertyChangeEvent getEvent() {
return this.event;
}
/**
* Sets the target event.
*
* @param event
* the event to set.
* @return <code>this</code>.
*/
public final FocusGainedBean setEvent(PropertyChangeEvent event) {
Assert.notNull(event, "event");
this.event = event;
return this;
}
/**
* Gets the old focused component propagated by an event.
*
* @return the component.
*/
public final Component getOldComponent() {
final Component oldComponent;
if ((this.getEvent() != null) && this.getEvent().getOldValue() instanceof Component) {
oldComponent = (Component) this.getEvent().getOldValue();
} else {
oldComponent = null;
}
return oldComponent;
}
/**
* Gets the new focused component propagated by an event.
*
* @return the component.
*/
public final Component getNewComponent() {
final Component newComponent;
if ((this.getEvent() != null) && this.getEvent().getNewValue() instanceof Component) {
newComponent = (Component) this.getEvent().getNewValue();
} else {
newComponent = null;
}
return newComponent;
}
/**
* Gets the last active title bar.
*
* @return the last active title bar.
*/
public final DockViewTitleBar getLastTitleBar() {
return this.lastTitleBar;
}
/**
* Sets the last active title bar.
*
* @param lastActiveTitleBar
* the last active title bar to set.
*
* @return <code>this</code>.
*/
public final FocusGainedBean setLastTitleBar(DockViewTitleBar lastActiveTitleBar) {
this.lastTitleBar = lastActiveTitleBar;
return this;
}
/**
* Gets the old focused title bar propagated by an event.
*
* @return the title bar.
*/
public final DockViewTitleBar getOldTitleBar() {
return VLDockingUtils.nullSafeFindDockViewTitleBar(this.getOldComponent());
}
/**
* Gets the new focused title bar propagated by an event.
*
* @return the title bar.
*/
public final DockViewTitleBar getNewTitleBar() {
return VLDockingUtils.nullSafeFindDockViewTitleBar(this.getNewComponent());
}
/**
* Gets the description of what's happening.
*
* @return the description.
*/
public final String getWhatsHappening() {
return this.whatsHappening;
}
/**
* Sets the description of what's happening.
*
* @param whatsHappening
* the description to set.
*
* @return <code>this</code>.
*/
public final FocusGainedBean setWhatsHappening(String whatsHappening) {
Assert.notNull(whatsHappening, "whatsHappening");
this.whatsHappening = whatsHappening;
return this;
}
// /** //TODO
// * {@inheritDoc}
// */
// @Override
// public String toString() {
//
//// return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) //
//// .append(FocusGainedBean.instanceCount) //
//// .append(this.getWhatsHappening()) //
//// .append("lastTitleBar", this.titleBarToString(this.getLastTitleBar()))//
//// .append("oldTitleBar", this.titleBarToString(this.getOldTitleBar())) //
//// .append("newTitleBar", this.titleBarToString(this.getNewTitleBar())) //
//// .append("oldComponent", this.componentToString(this.getOldComponent()))//
//// .append("newComponent", this.componentToString(this.getNewComponent()))//
//// .toString();
// }
/**
* Returns a legible representation of a given component.
*
* @param component
* the target component.
* @return a string.
*/
private String componentToString(Component component) {
final StringBuffer sb = new StringBuffer();
sb.append(ObjectUtils.identityToString(component));
if (component != null) {
sb.append(": ").append((component.getName() != null) ? component.getName() : component.toString());
}
return sb.toString();
}
/**
* Returns a legible representation of a given dockable.
*
* @param titleBar
* the target title bar.
* @return a string.
*/
private String titleBarToString(DockViewTitleBar titleBar) {
final StringBuffer sb = new StringBuffer();
sb.append(ObjectUtils.identityToString(titleBar));
final Character prefix;
final String text;
if (titleBar != null) {
prefix = titleBar.isActive() ? '+' : '-';
text = (titleBar.getDockable() != null) ? titleBar.getDockable().getDockKey().getName() : null;
} else {
prefix = '-';
text = null;
}
sb.append(prefix).append(text);
return sb.toString();
}
}
/**
* A set of colors with its own semantic.
*
* @author <a href = "mailto:julio.arguello@gmail.com" >Julio Arg??ello (JAF)</a>
*/
public static enum DockingColor {
/**
* The active widget color.
*/
ACTIVE_WIDGET("Bluebell.activeWidgetColor"), // instead of "activeCaption"
/**
* The inactive widget color.
*/
INACTIVE_WIDGET("Bluebell.inactiveWidgetColor"), // instead of ""controlLtHighlight""
/**
* The background color.
*/
BACKGROUND("Bluebell.backgroundColor"), // instead of control "DockingDesktop.backgroundColor"
/**
* The highlight color.
*/
HIGHLIGHT("Bluebell.highlightColor"), // instead of "controlHighlight"
/**
* The shadow color.
*/
SHADOW("Bluebell.shadowColor"); // controlDkShadow
/**
* The key to query the UIManager for getting the associated color.
*/
private String key;
/**
* Creates the enumerated type.
*
* @param key
* the key to query the UIManager.
*/
private DockingColor(String key) {
this.setKey(key);
}
/**
* Gets the related color.
*
* @return the related color.
*/
public Color getColor() {
return UIManager.getColor(this.getKey());
}
/**
* Gets the key.
*
* @return the key
*/
public String getKey() {
return this.key;
}
/**
* Sets the key.
*
* @param key
* the key to set.
*/
private void setKey(String key) {
Assert.notNull(key, "key");
this.key = key;
}
}
/**
* An enum to distinguish between dock view types.
*
* @author <a href = "mailto:julio.arguello@gmail.com" >Julio Arg??ello (JAF)</a>
*/
public static enum DockViewType {
/**
* Closed dockable state.
*/
CLOSED,
/**
* Docked dockable state.
*/
DOCKED,
/**
* Floating dockable state.
*/
FLOATING,
/**
* Hidden dockable state.
*/
HIDDEN,
/**
* Maximized dockable state.
*/
MAXIMIZED,
/**
* Tabbed dockable state.
*/
TABBED
}
}