package org.webcat.ui;
import com.webobjects.appserver.WOApplication;
import com.webobjects.appserver.WOComponent;
import com.webobjects.appserver.WOContext;
import com.webobjects.appserver.WOElement;
import com.webobjects.appserver.WORequest;
import com.webobjects.appserver.WOResponse;
import com.webobjects.appserver._private.WOElementID;
import com.webobjects.foundation.NSBundle;
import com.webobjects.foundation.NSKeyValueCoding;
import com.webobjects.foundation.NSKeyValueCodingAdditions;
import er.ajax.AjaxUtils;
import er.extensions.components.ERXComponentUtilities;
import er.extensions.foundation.ERXStringUtilities;
public class WCTitlePane extends WOComponent
{
//~ Constructors ..........................................................
// ----------------------------------------------------------
public WCTitlePane(WOContext context)
{
super(context);
titlePaneBindings = new BindingsProxy();
}
//~ KVC attributes (must be public) .......................................
public BindingsProxy titlePaneBindings;
//~ Methods ...............................................................
// ----------------------------------------------------------
/**
* This component uses a template that is generated at runtime in order to
* pass its bindings directly to the content pane that it contains.
*
* @return the template
*/
@Override
public WOElement template()
{
if (cachedTemplate == null)
{
cachedTemplate = WOComponent.templateWithHTMLString(
NSBundle.bundleForClass(getClass()).name(), name(),
TEMPLATE_HTML, declarationStringWithBindings(), null,
WOApplication.application().associationFactory(),
WOApplication.application().namespaceProvider());
}
return cachedTemplate;
}
// ----------------------------------------------------------
@Override
public boolean synchronizesVariablesWithBindings()
{
return false;
}
// ----------------------------------------------------------
/**
* Returns true if the content of this title pane should take part in the
* request/response cycle (that is, if it should be rendered or asked to
* take values or invoke actions).
*
* @return true if the content should be rendered; otherwise, false
*/
public boolean shouldProcessContent()
{
if (!wasContentRendered)
{
WOContext context = context();
boolean isInitiallyOpen = valueForBooleanBinding("open", true);
boolean isLoadingNow = false;
if (context.elementID() != null && context.senderID() != null)
{
boolean isAjax = AjaxUtils.isAjaxRequest(context.request());
WOElementID elementID = new WOElementID(context.elementID());
elementID.deleteLastElementIDComponent();
String parentID = elementID.toString();
// ... if the request is an AJAX request that was sent by the
// enclosing content pane (meaning the pane is trying to load
// itself), or if the request is any request (AJAX or not) sent
// by a child of the pane (meaning it must have been opened and
// loaded for something inside it to send a request).
isLoadingNow =
(isAjax && parentID.equals(context.senderID()));
}
wasContentRendered = isInitiallyOpen || isLoadingNow;
}
return wasContentRendered;
}
// ----------------------------------------------------------
/**
* Passes any bindings associated with this WCTitlePane component to the
* WCContentPane that will be embedded inside it. This method essentially
* just adds a set of "binding = binding" lines to the WOD declaration of
* the template, and {@link #handleQueryWithUnboundKey(String)} will grab
* the correct values from this component to give to the content pane.
*
* @return the WOD template string
*/
public String declarationStringWithBindings()
{
StringBuffer buffer = new StringBuffer(32);
for (String binding : bindingKeys())
{
buffer.append(binding);
buffer.append(" = titlePaneBindings.");
buffer.append(binding);
buffer.append(";\n");
}
String wod = TEMPLATE_WOD.replaceFirst("\\$\\{otherBindings\\}",
buffer.toString());
return wod;
}
//~ Private classes .......................................................
// ----------------------------------------------------------
/**
* Allows the title pane's bindings to pass through seamlessly to the
* content pane contained in the template.
*/
private class BindingsProxy implements NSKeyValueCoding
{
// ----------------------------------------------------------
public void takeValueForKey(Object value, String key)
{
WCTitlePane pane = WCTitlePane.this;
if (pane.hasBinding(key))
{
pane.setValueForBinding(value, key);
}
else
{
NSKeyValueCoding.DefaultImplementation.takeValueForKey(
this, value, key);
}
}
// ----------------------------------------------------------
public Object valueForKey(String key)
{
WCTitlePane pane = WCTitlePane.this;
if (pane.hasBinding(key))
{
return pane.valueForBinding(key);
}
else
{
return NSKeyValueCoding.DefaultImplementation.valueForKey(
this, key);
}
}
}
//~ Static/instance variables .............................................
private WOElement cachedTemplate;
private boolean wasContentRendered;
private static final String TEMPLATE_HTML =
"<wo name=\"TitlePane\">" +
"<wo name=\"ShouldProcessChildren\">" +
"<wo name=\"ComponentContent\" />" +
"</wo>" +
"</wo>";
private static final String TEMPLATE_WOD =
"TitlePane : WCContentPane {\n" +
"dojoType = \"webcat.TitlePane\";\n" +
"${otherBindings}" +
"}\n" +
"ShouldProcessChildren : WOConditional {\n" +
"condition = shouldProcessContent;\n" +
"}\n" +
"ComponentContent : WOComponentContent { }\n";
}