/**
* 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.form.builder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.valkyriercp.binding.form.FieldMetadata;
import org.valkyriercp.binding.form.FormModel;
import org.valkyriercp.binding.value.ValueModel;
import org.valkyriercp.component.OverlayService;
import org.valkyriercp.util.ValkyrieRepository;
import javax.swing.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
public abstract class AbstractOverlayFormComponentInterceptor extends AbstractFormComponentInterceptor {
/**
* The "ancestor" property name.
*/
private static final String ANCESTOR_PROPERTY = "ancestor";
/**
* The overlay service.
*/
@Autowired
private OverlayService overlayService;
/**
* Creates the interceptor given the target form model.
*
* @param formModel
* the form model.
*/
public AbstractOverlayFormComponentInterceptor(FormModel formModel) {
super(formModel);
}
/**
* Gets the overlay service.
*
* @return the overlay service.
*/
public final OverlayService getOverlayService() {
if(overlayService == null)
return ValkyrieRepository.getInstance().getApplicationConfig().overlayService();
return this.overlayService;
}
/**
* Sets the overlay service.
*
* @param overlayService
* the overlay service to set.
*/
public final void setOverlayService(OverlayService overlayService) {
Assert.notNull(overlayService, "overlayService");
this.overlayService = overlayService;
}
/**
* Creates an overlay handler for the given property name and component and installs the overlay.
*
* @param propertyName
* the property name.
*
* @param component
* the component.
*
* @see OverlayService#installOverlay(JComponent, JComponent)
*/
@Override
public final void processComponent(String propertyName, final JComponent component) {
final AbstractOverlayHandler overlayHandler = this.createOverlayHandler(propertyName, component);
// Wait until has parent and overlay is correctly installed
final PropertyChangeListener wait4ParentListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
final JComponent targetComponent = overlayHandler.getTargetComponent();
final JComponent overlay = overlayHandler.getOverlay();
// Install overlay
final int position = AbstractOverlayFormComponentInterceptor.this.getPosition();
final Boolean success = AbstractOverlayFormComponentInterceptor.this.//
getOverlayService().installOverlay(targetComponent, overlay, position, null);
if (success) {
targetComponent.removePropertyChangeListener(//
AbstractOverlayFormComponentInterceptor.ANCESTOR_PROPERTY, this);
}
}
};
component.addPropertyChangeListener(//
AbstractOverlayFormComponentInterceptor.ANCESTOR_PROPERTY, wait4ParentListener);
}
/**
* Gets the position where overlay should be installed.
* <p>
* Note installing more than one overlays at the same position will be confused.
*
* @return the position.
*/
protected abstract int getPosition();
/**
* Creates the overlay handler for the given property name and component.
*
* @param propertyName
* the property name.
* @param component
* the component.
* @return the overlay handler.
*/
protected abstract AbstractOverlayHandler createOverlayHandler(String propertyName, final JComponent component);
/**
* An overlay handler that knows the name, component and form model of the target property.
*/
protected abstract class AbstractOverlayHandler {
/**
* The property name.
*/
private String propertyName;
/**
* The target component.
*/
private JComponent targetComponent;
/**
* The overlay component.
*/
private JComponent overlay;
/**
* Creates the handler given the target component.
*
* @param propertyName
* the property name.
*
* @param targetComponent
* the target component.
*/
public AbstractOverlayHandler(String propertyName, JComponent targetComponent) {
this.setPropertyName(propertyName);
this.setTargetComponent(targetComponent);
}
/**
* Shows or hides the overlay.
*
* @param show
* whether to show or hide the overlay.
*
* @return <code>true</code> if success and <code>false</code> in other case.
*/
protected final Boolean refreshOverlay(Boolean show) {
if (show) {
return this.showOverlay();
} else {
return this.hideOverlay();
}
}
/**
* Shows the overlay.
*
* @return <code>true</code> if success and <code>false</code> in other case.
*/
protected Boolean showOverlay() {
this.getOverlay().setSize(this.getOverlay().getPreferredSize());
return AbstractOverlayFormComponentInterceptor.this.getOverlayService().showOverlay(//
this.getTargetComponent(), this.getOverlay());
}
/**
* Hides the overlay.
*
* @return <code>true</code> if success and <code>false</code> in other case.
*/
protected Boolean hideOverlay() {
return AbstractOverlayFormComponentInterceptor.this.getOverlayService().hideOverlay(//
this.getTargetComponent(), this.getOverlay());
}
/**
* Gets the form model.
*
* @return the form model.
*/
protected FormModel getFormModel() {
return AbstractOverlayFormComponentInterceptor.this.getFormModel();
}
/**
* Gets the value model.
*
* @return the value model.
*/
protected ValueModel getValueModel() {
return this.getFormModel().getValueModel(this.getPropertyName());
}
/**
* Gets the field metada.
*
* @return the field metadata.
*/
protected FieldMetadata getFieldMetadata() {
return this.getFormModel().getFieldMetadata(this.getPropertyName());
}
/**
* Gets the property name.
*
* @return the property name.
*/
protected final String getPropertyName() {
return this.propertyName;
}
/**
* Gets the target component.
*
* @return the target component.
*/
protected final JComponent getTargetComponent() {
return this.targetComponent;
}
/**
* Gets the overlay component and if not exists then create it.
*
* @return the overlay.
*
* @see #createOverlay()
*/
protected final JComponent getOverlay() {
if (this.overlay == null) {
this.setOverlay(this.createOverlay());
}
return this.overlay;
}
/**
* Creates the overlay component.
*
* @return the overlay.
*/
protected abstract JComponent createOverlay();
/**
* Sets the propertyName.
*
* @param propertyName
* the propertyName to set.
*/
private void setPropertyName(String propertyName) {
Assert.notNull(propertyName, "propertyName");
this.propertyName = propertyName;
}
/**
* Sets the target component.
*
* @param targetComponent
* the target component to set.
*/
private void setTargetComponent(JComponent targetComponent) {
Assert.notNull(targetComponent, "targetComponent");
this.targetComponent = targetComponent;
}
/**
* Sets the overlay.
*
* @param overlay
* the overlay to set.
*/
private void setOverlay(JComponent overlay) {
Assert.notNull(overlay, "overlay");
this.overlay = overlay;
}
}
}