package pt.ist.vaadinframework.example.ui; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import org.apache.commons.lang.StringUtils; import com.vaadin.data.Property; import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeListener; import com.vaadin.data.util.BeanItem; import com.vaadin.data.util.HierarchicalContainer; import com.vaadin.event.Action; import com.vaadin.event.DataBoundTransferable; import com.vaadin.event.dd.DragAndDropEvent; import com.vaadin.event.dd.DropHandler; import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; import com.vaadin.event.dd.acceptcriteria.SourceIsTarget; import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation; import com.vaadin.ui.CustomComponent; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.RichTextArea; import com.vaadin.ui.TextField; import com.vaadin.ui.Tree; import com.vaadin.ui.Tree.TreeDragMode; import com.vaadin.ui.Tree.TreeTargetDetails; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.Window.Notification; @SuppressWarnings("serial") public class Wiki extends CustomComponent { public class Section implements Serializable { private String title; private String content; private Section parent; private final Collection
children = new ArrayList
(); public Section(String title) { this.title = title; } public Section(Section parent, String title) { this.parent = parent; parent.addSection(this); this.title = title; } public boolean isRoot() { return parent == null; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Collection
getSections() { return children; } public void addSectionAfterChild(Section section, Section child) { } public void addSection(Section section) { } public void delete() { // TODO } @Override public String toString() { return title; } } public static final Action newSection = new Action("Criar Secção"); public static final Action delete = new Action("Apagar Secção"); private final Section document = new Section("Root"); private Tree sections; private RichTextArea editor; private TextField title; public Wiki() { HorizontalLayout layout = new HorizontalLayout(); layout.setWidth("100%"); layout.setSpacing(true); sections = new Tree(); layout.addComponent(sections); sections.setCaption("Secções"); sections.setImmediate(true); sections.setDragMode(TreeDragMode.NODE); sections.addActionHandler(new TreeContextHandler()); sections.setDropHandler(new SectionDropHandler()); sections.addListener(new Property.ValueChangeListener() { private static final long serialVersionUID = 1L; @Override public void valueChange(ValueChangeEvent event) { if (event.getProperty().getValue() != null) { Section section = (Section) event.getProperty().getValue(); if (!section.isRoot()) { BeanItem
item = new BeanItem
(section); title.setPropertyDataSource(item.getItemProperty("title")); title.setEnabled(true); title.requestRepaint(); editor.setPropertyDataSource(item.getItemProperty("content")); editor.setEnabled(true); editor.requestRepaint(); return; } } title.setPropertyDataSource(null); title.setEnabled(false); editor.setPropertyDataSource(null); editor.setEnabled(false); } }); VerticalLayout editorLayout = new VerticalLayout(); layout.addComponent(editorLayout); layout.setExpandRatio(editorLayout, 1f); editorLayout.setSpacing(true); editorLayout.setWidth("100%"); title = new TextField("Título"); editorLayout.addComponent(title); title.setWidth("100%"); title.setImmediate(true); title.setWriteThrough(true); title.setEnabled(false); title.addListener(new ValueChangeListener() { private static final long serialVersionUID = 1L; @Override public void valueChange(ValueChangeEvent event) { sections.requestRepaint(); } }); editor = new RichTextArea(); editor.setNullSettingAllowed(true); editor.setNullRepresentation(StringUtils.EMPTY); editorLayout.addComponent(editor); editor.setWidth("100%"); editor.setHeight("350px"); editor.setImmediate(true); editor.setWriteThrough(true); editor.setEnabled(false); final String editor1InitialValue = ""; editor.setValue(editor1InitialValue); setCompositionRoot(layout); } @Override public void attach() { super.attach(); HierarchicalContainer tree = new HierarchicalContainer(); parseSections(tree, null, Collections.singleton(document)); sections.setContainerDataSource(tree); for (Object itemId : tree.rootItemIds()) { sections.expandItemsRecursively(itemId); } } private void parseSections(HierarchicalContainer tree, Section section, Collection
children) { if (section != null) { tree.setChildrenAllowed(section, true); } Iterator
iterator = children.iterator(); Section previous = null; while (iterator.hasNext()) { Section child = iterator.next(); tree.addItem(child); tree.setParent(child, section); tree.moveAfterSibling(child, previous); tree.setChildrenAllowed(child, false); previous = child; parseSections(tree, child, child.getSections()); } } public class SectionDropHandler implements DropHandler { private static final long serialVersionUID = 1L; @Override public void drop(DragAndDropEvent event) { if (event.getTransferable() instanceof DataBoundTransferable) { DataBoundTransferable transferable = (DataBoundTransferable) event.getTransferable(); TreeTargetDetails data = (TreeTargetDetails) event.getTargetDetails(); Object source = transferable.getItemId(); Object targetAfter = data.getItemIdAfter(); Object targetInto = data.getItemIdInto(); Object targetOver = data.getItemIdOver(); VerticalDropLocation location = data.getDropLocation(); getWindow().showNotification( "Source: " + source + "
Target After: " + targetAfter + "
Target Into: " + targetInto + "
Target Over: " + targetOver + "
Location: " + location, Notification.TYPE_HUMANIZED_MESSAGE); move((Section) transferable.getItemId(), (Section) data.getItemIdOver(), data.getDropLocation()); } } private void move(Section source, Section over, VerticalDropLocation location) { HierarchicalContainer container = (HierarchicalContainer) sections.getContainerDataSource(); Section parent = (Section) container.getParent(over); switch (location) { case BOTTOM: if (!over.isRoot()) { if (container.setParent(source, parent)) { container.moveAfterSibling(source, over); parent.addSectionAfterChild(source, over); } } break; case MIDDLE: container.setChildrenAllowed(over, true); if (container.setParent(source, over)) { container.moveAfterSibling(source, null); sections.expandItemsRecursively(over); over.addSection(source); } break; case TOP: if (!over.isRoot()) { if (container.setParent(source, parent)) { container.moveAfterSibling(over, source); parent.addSectionAfterChild(over, source); } } break; default: break; } } @Override public AcceptCriterion getAcceptCriterion() { return SourceIsTarget.get(); } } public class TreeContextHandler implements Action.Handler { @Override public Action[] getActions(Object target, Object sender) { return new Action[] { newSection, delete }; } @Override public void handleAction(Action action, Object sender, Object target) { HierarchicalContainer container = (HierarchicalContainer) sections.getContainerDataSource(); Section targetSection = (Section) target; if (action == newSection) { Section child = new Section(targetSection, "Nova Secção"); container.addItem(child); if (container.setParent(child, targetSection)) { container.moveAfterSibling(child, null); sections.expandItemsRecursively(targetSection); } } else if (action == delete) { container.removeItem(targetSection); targetSection.delete(); } } } }