package org.sigmah.client.ui.widget.form;
/*
* #%L
* Sigmah
* %%
* Copyright (C) 2010 - 2016 URD
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import java.util.HashMap;
import java.util.Map;
import com.extjs.gxt.ui.client.core.El;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.event.TabPanelEvent;
import com.extjs.gxt.ui.client.widget.ComponentHelper;
import com.extjs.gxt.ui.client.widget.Layout;
import com.extjs.gxt.ui.client.widget.TabItem;
import com.extjs.gxt.ui.client.widget.TabPanel;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.form.*;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import org.sigmah.client.dispatch.DispatchAsync;
import org.sigmah.client.dispatch.DispatchQueue;
import org.sigmah.client.i18n.I18N;
import org.sigmah.client.ui.notif.ConfirmCallback;
import org.sigmah.client.ui.notif.N10N;
import org.sigmah.client.ui.res.icon.IconImageBundle;
import org.sigmah.client.ui.widget.button.Button;
import org.sigmah.client.ui.widget.layout.Layouts;
import org.sigmah.shared.command.UpdateLayoutGroupIterations.IterationChange;
import org.sigmah.shared.dto.element.FlexibleElementContainer;
import org.sigmah.shared.dto.element.FlexibleElementDTO;
import org.sigmah.shared.dto.layout.LayoutGroupDTO;
/**
* Custom {@link com.extjs.gxt.ui.client.widget.TabPanel} implementation.
*
* @see Forms
*/
public class IterableGroupPanel extends TabPanel {
public static class IterableGroupItem extends TabItem {
private IterableGroupPanel parent;
private int iterationId;
private String iterationName;
private Map<FlexibleElementDTO, Boolean> mandatoryElements = new HashMap<FlexibleElementDTO, Boolean>();
private Button btnRename;
public IterableGroupItem(IterableGroupPanel parent, int iterationId, String iterationName) {
super();
this.parent = parent;
this.iterationId = iterationId;
this.iterationName = iterationName;
if(parent.canEdit) {
generateToolBar();
}
}
public int getIterationId() {
return iterationId;
}
public void setIterationId(int iterationId) {
this.iterationId = iterationId;
}
public String getIterationName() {
return iterationName;
}
public void setIterationName(String iterationName) {
this.iterationName = iterationName;
refreshRenameButton();
refreshTitle();
}
public void setElementValidity(FlexibleElementDTO element, boolean valid) {
mandatoryElements.put(element, valid);
revalidateElements();
}
public void revalidateElements() {
boolean valid = true;
for (Boolean elementValid : mandatoryElements.values()) {
if (!elementValid) {
valid = false;
}
}
if (valid) {
getHeader().setIcon(IconImageBundle.ICONS.elementCompleted());
} else {
getHeader().setIcon(IconImageBundle.ICONS.elementUncompleted());
}
}
public void refreshTitle() {
String name = iterationName!=null?iterationName:"";
String title = (parent.getItems().indexOf(this) + 1) + ". " + name;
getHeader().setText(title);
}
private void generateToolBar() {
btnRename = new Button();
btnRename.addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent menuEvent) {
renameTab();
}
});
refreshRenameButton();
Button btnRemove = new Button(I18N.CONSTANTS.layoutGroupIterationRemoveButton());
btnRemove.addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent menuEvent) {
removeTab();
}
});
ToolBar tb = new ToolBar();
tb.setAutoHeight(true);
tb.add(btnRename);
tb.add(btnRemove);
add(tb);
}
private void refreshRenameButton() {
if(getIterationName() == null || "".equals(getIterationName())) {
btnRename.setText(I18N.CONSTANTS.layoutGroupIterationSetNameButton());
} else {
btnRename.setText(I18N.CONSTANTS.layoutGroupIterationRenameButton());
}
}
private void renameTab() {
final Window w = new Window();
w.setHeadingText(I18N.CONSTANTS.layoutGroupIterationRename());
w.setPlain(true);
w.setModal(true);
w.setBlinkModal(true);
w.setLayout(new FitLayout());
w.setSize(500, 100);
final TextField<String> field = new TextField<String>();
field.setFieldLabel(I18N.CONSTANTS.layoutGroupIterationName());
field.setValue(getIterationName());
Button btn = Forms.button(I18N.CONSTANTS.ok());
btn.addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent buttonEvent) {
String tabName = field.getValue();
setIterationName(tabName);
parent.iterationNameChanged(iterationId, tabName);
w.hide();
}
});
com.extjs.gxt.ui.client.widget.form.FormPanel fp = new com.extjs.gxt.ui.client.widget.form.FormPanel();
fp.setHeaderVisible(false);
fp.setLayout(Forms.layout(150, 300));
fp.add(field);
fp.getButtonBar().add(btn);
w.add(fp);
w.show();
}
private void removeTab() {
N10N.confirmation(I18N.CONSTANTS.layoutGroupIterationDelete(), I18N.CONSTANTS.layoutGroupIterationDeleteConfirm(), new ConfirmCallback() {
@Override
public void onAction() {
parent.removeTab(iterationId);
}
});
}
}
public interface Delegate {
FieldSet createGroupLayoutFieldSet(FlexibleElementContainer container, LayoutGroupDTO layoutGroup, DispatchQueue queue, Integer iterationId, IterableGroupPanel tabPanel, IterableGroupItem tabItem);
void addIterationTabItem(int iterationId, IterableGroupItem tab);
IterationChange getIterationChange(int iterationId);
void setIterationChange(IterationChange iterationChange);
}
/**
* Application command dispatcher.
*/
protected final DispatchAsync dispatch;
/**
* Next temporary iterationId (used until database insertion)
*/
private int nextIterationId = -1;
/**
* Iterative group corresponding to this TabPanel
*/
private LayoutGroupDTO layoutGroup;
private FlexibleElementContainer container;
private final boolean canEdit;
private Delegate delegate;
public IterableGroupPanel(final DispatchAsync dispatch, final LayoutGroupDTO layoutGroup, FlexibleElementContainer container, final boolean canEdit) {
super();
this.dispatch = dispatch;
this.container = container;
this.layoutGroup = layoutGroup;
this.canEdit = canEdit;
if(canEdit) {
addListener(Events.Render, new Listener<TabPanelEvent>() {
@Override
public void handleEvent(TabPanelEvent tpe) {
El strip = el().childNode(0).childNode(0).childNode(0);
int clearIdx = strip.getChildIndex(strip.lastChild().dom);
Button button = new Button("+");
button.setEnabled(canEdit);
button.render(strip.dom, clearIdx - 1);
ComponentHelper.doAttach(button);
button.addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent ce) {
addEmptyTab();
}
});
}
});
}
}
private void addEmptyTab() {
if (delegate != null) {
final Window w = new Window();
w.setHeadingText(I18N.CONSTANTS.layoutGroupIterationCreation());
w.setPlain(true);
w.setModal(true);
w.setBlinkModal(true);
w.setLayout(new FitLayout());
w.setSize(500, 100);
final TextField<String> field = new TextField<String>();
field.setFieldLabel(I18N.CONSTANTS.layoutGroupIterationName());
Button btn = Forms.button(I18N.CONSTANTS.ok());
btn.addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent buttonEvent) {
DispatchQueue queue = new DispatchQueue(dispatch, true);
String tabName = field.getValue();
int iterationId = getTemporaryIterationId();
final IterableGroupItem tab = new IterableGroupItem(IterableGroupPanel.this, iterationId, tabName);
addIterationTab(tab);
delegate.addIterationTabItem(iterationId, tab);
Layout tabLayout = Layouts.fitLayout();
tab.setLayout(tabLayout);
FieldSet tabSet = delegate.createGroupLayoutFieldSet(container, layoutGroup, queue, iterationId, IterableGroupPanel.this, tab);
tab.add(tabSet);
queue.start();
setSelection(tab);
IterationChange ic = new IterationChange();
ic.setIterationId(iterationId);
ic.setName(tabName);
ic.setLayoutGroupId(layoutGroup.getId());
delegate.setIterationChange(ic);
w.hide();
}
});
FormPanel fp = new FormPanel();
fp.setHeaderVisible(false);
fp.setLayout(Forms.layout(150, 300));
fp.add(field);
fp.getButtonBar().add(btn);
w.add(fp);
w.show();
}
}
public void addIterationTab(final IterableGroupItem item) {
super.add(item);
item.refreshTitle();
}
private void removeTab(int iterationId) {
if (delegate != null) {
IterationChange ic = delegate.getIterationChange(iterationId);
if (ic == null) {
ic = new IterationChange();
ic.setIterationId(iterationId);
}
ic.setDeleted(true);
ic.setLayoutGroupId(layoutGroup.getId());
delegate.setIterationChange(ic);
}
remove(getSelectedItem());
refreshTabNames();
}
private void refreshTabNames() {
for (int i = 0; i < getItemCount(); i++) {
((IterableGroupItem) getItem(i)).refreshTitle();
}
}
public void setElementValidity(FlexibleElementDTO element, boolean valid) {
((IterableGroupItem) getSelectedItem()).setElementValidity(element, valid);
}
public void validateElements() {
for (TabItem item : getItems()) {
((IterableGroupItem) item).revalidateElements();
}
}
public Integer getCurrentIterationId() {
return ((IterableGroupItem) getSelectedItem()).getIterationId();
}
public int getTemporaryIterationId() {
return nextIterationId--;
}
public void setDelegate(Delegate delegate) {
this.delegate = delegate;
}
private void iterationNameChanged(int iterationId, String newName) {
IterationChange ic = delegate.getIterationChange(iterationId);
if (ic == null) {
ic = new IterationChange();
ic.setIterationId(iterationId);
}
ic.setName(newName);
ic.setLayoutGroupId(layoutGroup.getId());
delegate.setIterationChange(ic);
}
}