/*
* Copyright (c) 2011-2014 Fernando Petrola
*
* 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 com.dragome.forms.bindings.builders;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.dragome.forms.bindings.client.form.binding.FormBinder;
import com.dragome.forms.bindings.client.form.metadata.binding.ConditionBinderBuilder;
import com.dragome.forms.bindings.client.style.StyleBinder;
import com.dragome.forms.bindings.client.style.StyleBindingBuilder;
import com.dragome.forms.bindings.client.style.StyleBuilder;
import com.dragome.guia.components.interfaces.VisualComponent;
import com.dragome.guia.components.interfaces.VisualPanel;
import com.dragome.guia.events.listeners.interfaces.BlurListener;
import com.dragome.guia.events.listeners.interfaces.ClickListener;
import com.dragome.guia.events.listeners.interfaces.DoubleClickListener;
import com.dragome.guia.events.listeners.interfaces.InputListener;
import com.dragome.guia.events.listeners.interfaces.KeyUpListener;
import com.dragome.model.interfaces.ValueChangeEvent;
import com.dragome.model.interfaces.ValueChangeHandler;
import com.dragome.model.pectin.VisualComponentHasEnabled;
public abstract class BaseBuilder<C extends VisualComponent, B extends BaseBuilder<C, B>>
{
protected BaseBuilder<? extends VisualComponent, B> parentBuilder;
public BaseBuilder<? extends VisualComponent, B> getParentBuilder()
{
return parentBuilder;
}
public void setParentBuilder(BaseBuilder<? extends VisualComponent, B> parentBuilder)
{
this.parentBuilder= parentBuilder;
}
protected ConditionBinderBuilder<?> conditionBinderBuilder;
protected FormBinder binder= new FormBinder();
protected C component;
private StyleBinder styleBinder= new StyleBinder();
private StyleBinder styleBinder2= new StyleBinder();
private StyleBuilder styleBuilder;
private StyleBuilder styleBuilder2;
private StyleBindingBuilder styleBindingBuilder;
private StyleBindingBuilder styleBindingBuilder2;
private ValueModelDelegator<Object> switchSource;
private List<Case> cases= new ArrayList<Case>();
private boolean buildEnding= false;
public BaseBuilder()
{
}
public BaseBuilder<? extends VisualComponent, B> parentBuilder()
{
return parentBuilder;
}
public B show(C visualComponent)
{
conditionBinderBuilder= binder.show(visualComponent);
return (B) this;
}
public B styleWith(String trueClassName, String falseClassName)
{
B style= style(component);
return style.with(trueClassName, falseClassName);
}
public B styleWith(String className)
{
return style(component).with(className);
}
public B showWhen(Supplier<Boolean> supplier)
{
return show(component).when(supplier);
}
public B disable(C visualComponent)
{
conditionBinderBuilder= binder.disable(new VisualComponentHasEnabled(component));
return (B) this;
}
public B disableWhen(Supplier<Boolean> supplier)
{
return disable(component).when(supplier);
}
public B with(String className)
{
styleBindingBuilder= styleBuilder.with(className);
return (B) this;
}
public B style(VisualComponent component)
{
styleBuilder= styleBinder.style(component);
styleBuilder2= styleBinder2.style(component);
return (B) this;
}
public B when(Supplier<Boolean> object)
{
build();
ValueModelDelegator<Boolean> condition= BindingSync.createCondition(object);
if (conditionBinderBuilder != null)
{
conditionBinderBuilder.when(condition);
conditionBinderBuilder= null;
}
else
{
styleBindingBuilder.when(condition);
styleBindingBuilder= null;
}
return (B) this;
}
public B with(String trueClassName, String falseClassName)
{
styleBindingBuilder= styleBuilder.with(trueClassName);
styleBindingBuilder2= styleBuilder2.with(falseClassName);
return (B) this;
}
public B accordingTo(final Supplier<Boolean> object)
{
build();
styleBindingBuilder.when(BindingSync.createCondition(object));
styleBindingBuilder2.when(BindingSync.createCondition(new Supplier<Boolean>()
{
public Boolean get()
{
return !object.get();
}
}));
return (B) this;
}
public <S> B switchWith(Supplier<S> supplier)
{
this.switchSource= (ValueModelDelegator<Object>) BindingSync.createCondition(supplier);
this.switchSource.addValueChangeHandler(new ValueChangeHandler<Object>()
{
public void onValueChange(ValueChangeEvent<Object> event)
{
updateCases();
}
});
return (B) this;
}
public void addCase(Case aCase)
{
cases.add(aCase);
}
public void updateCases()
{
if (switchSource != null)
{
Object value= switchSource.getValue();
Case defaultCase= null;
Case found= null;
for (Case currentCase : cases)
{
currentCase.hide();
if (currentCase.isDefaultCase())
defaultCase= currentCase;
else if (currentCase.getSupplier().get().equals(value))
found= currentCase;
}
if (found == null)
found= defaultCase;
found.show();
found.build();
}
}
public abstract C build();
public ComponentBuilder childrenBuilder()
{
return new ComponentBuilder(component, this);
}
public ComponentBuilder buildChildren(ChildrenBuilder childrenBuilder)
{
if (!buildEnding)
build();
ComponentBuilder builder= childrenBuilder();
childrenBuilder.build(builder);
if (buildEnding)
build();
updateCases();
return builder;
}
public B onDoubleClick(DoubleClickListener doubleClickPerformed)
{
component.addDoubleClickListener(doubleClickPerformed);
return (B) this;
}
public B onClick(ClickListener clickListener)
{
component.addClickListener(clickListener);
return (B) this;
}
public B onClick(final ActionExecutor actionExecutor)
{
component.addClickListener(new ClickListener()
{
public void clickPerformed(VisualComponent aVisualComponent)
{
actionExecutor.execute();
}
});
return (B) this;
}
public B onValueChange(final ActionExecutor actionExecutor)
{
component.addListener(ValueChangeHandler.class, new ValueChangeHandler()
{
public void onValueChange(ValueChangeEvent event)
{
actionExecutor.execute();
}
});
return (B) this;
}
public VisualComponent component()
{
return component;
}
public B onKeyUp(final KeyUpListener keyUpListener, final int... codes)
{
component.addKeyListener(new KeyUpListener()
{
public void keyupPerformed(VisualComponent visualComponent, int keyCode)
{
for (int code : codes)
{
if (code == keyCode || code == 0)
{
keyUpListener.keyupPerformed(visualComponent, keyCode);
break;
}
}
}
});
return (B) this;
}
public B onBlur(BlurListener blurListener)
{
component.addListener(BlurListener.class, blurListener);
return (B) this;
}
public B onInput(InputListener inputListener)
{
component.addListener(InputListener.class, inputListener);
return (B) this;
}
// private void switchCase(String templateName, CaseBuilder caseBuilder)
// {
// ComponentBuilder componentBuilder= (ComponentBuilder) this;
//
// parentBuilder.cases.add(new Case(caseBuilder, true, componentBuilder.bindTemplate(templateName)));
// }
// private <S> void switchWhen(String templateName, final Supplier<S> supplier, CaseBuilder caseBuilder)
// {
// ComponentBuilder componentBuilder= (ComponentBuilder) this;
//
// parentBuilder.cases.add(new Case(supplier, caseBuilder, componentBuilder.bindTemplate(templateName)));
// }
public void switchDefaultCase(CaseBuilder caseBuilder)
{
TemplateBindingBuilder componentBuilder= (TemplateBindingBuilder) this;
componentBuilder.getParentBuilder().cases.add(new Case(caseBuilder, true, componentBuilder));
}
public <S> void switchCase(Supplier<S> supplier, CaseBuilder caseBuilder)
{
TemplateBindingBuilder componentBuilder= (TemplateBindingBuilder) this;
componentBuilder.getParentBuilder().cases.add(new Case(supplier, caseBuilder, componentBuilder));
}
}