package nota.oxygen.common.list;
import java.util.ArrayList;
import java.util.List;
import nota.oxygen.common.BaseAuthorOperation;
import nota.oxygen.common.Utils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import ro.sync.ecss.extensions.api.ArgumentDescriptor;
import ro.sync.ecss.extensions.api.ArgumentsMap;
import ro.sync.ecss.extensions.api.AuthorDocumentController;
import ro.sync.ecss.extensions.api.AuthorOperationException;
import ro.sync.ecss.extensions.api.access.AuthorEditorAccess;
import ro.sync.ecss.extensions.api.node.AuthorElement;
import ro.sync.ecss.extensions.api.node.AuthorNode;
/**
* Indents the selected list items
* @author Ole Holst Andersen (oha@nota.nu)
*/
public class IndentListOperation extends BaseAuthorOperation {
@Override
protected void doOperation() throws AuthorOperationException {
try {
AuthorEditorAccess edtAccess = getAuthorAccess().getEditorAccess();
AuthorDocumentController docCtrl = getAuthorAccess().getDocumentController();
int selStart = getSelectionStart();
int selEnd = getSelectionEnd();
AuthorElement list = getNamedCommonParentElementOfSelection(listElement, null);
if (list==null) {
throw new AuthorOperationException("Current selection has no common parent "+listElement+" element");
}
List<AuthorNode> items = list.getContentNodes();
int firstItemIndex = 0;
for (int i=0; i<items.size(); i++)
{
AuthorNode item = items.get(i);
if (item.getType()!=AuthorNode.NODE_TYPE_ELEMENT) {
throw new AuthorOperationException("List contains non-element child");
}
if (selStart<item.getEndOffset())
{
firstItemIndex = i;
break;
}
}
int lastItemIndex = firstItemIndex;
while (lastItemIndex<items.size())
{
AuthorNode item = items.get(lastItemIndex);
if (item.getType()!=AuthorNode.NODE_TYPE_ELEMENT) {
throw new AuthorOperationException("List contains non-element child");
}
if (item.getEndOffset()+2>=selEnd) break;
lastItemIndex++;
}
// String itemsMsg = "Items";
// for (int i=0; i<items.size(); i++)
// {
// AuthorNode item = items.get(i);
// itemsMsg += "\n"+i+" from "+item.getStartOffset()+" to "+item.getEndOffset();
// }
// showMessage("Indenting items "+firstItemIndex+" until "+lastItemIndex+"\n"+itemsMsg+"\nCurrent selection: "+selStart+"-"+selEnd);
String xml = serialize(list);
Element listElem = Utils.deserializeElement(xml);
Element li = null;
NodeList children = listElem.getChildNodes();
List<Node> childrenToMove = new ArrayList<Node>();
for (int i=0; i<children.getLength(); i++) {
if (children.item(i).getLocalName().equals(itemElement)) {
li = (Element)children.item(i);
}
if (firstItemIndex<=i && i<=lastItemIndex) childrenToMove.add(children.item(i));
}
if (li==null) throw new AuthorOperationException("No list item was selected to indent");
Element nestedListElem = (Element)listElem.cloneNode(false);
nestedListElem.removeAttribute("id");
li = (Element)li.cloneNode(false);
li.removeAttribute("id");
li.appendChild(nestedListElem);
listElem.insertBefore(li, listElem.getChildNodes().item(firstItemIndex));
for (Node c : childrenToMove) {
nestedListElem.appendChild(listElem.removeChild(c));
}
docCtrl.deleteNode(list);
docCtrl.insertXMLFragment(Utils.serialize(listElem), edtAccess.getCaretOffset());
}
catch (Exception e)
{
if (e instanceof AuthorOperationException)
{
throw (AuthorOperationException)e;
}
else
{
throw new AuthorOperationException(
"Unexpected "+e.getClass().getName()+" occured: "+e.getMessage(),
e);
}
}
}
@Override
protected void parseArguments(ArgumentsMap args)
throws IllegalArgumentException {
listElement = (String)args.getArgumentValue(ARG_LIST_ELEMENT);
itemElement = (String)args.getArgumentValue(ARG_ITEM_ELEMENT);
}
private static String ARG_LIST_ELEMENT = "list element";
private static String ARG_ITEM_ELEMENT = "item element";
private String listElement;
private String itemElement;
@Override
public ArgumentDescriptor[] getArguments() {
return new ArgumentDescriptor[] {
new ArgumentDescriptor(ARG_LIST_ELEMENT, ArgumentDescriptor.TYPE_STRING, "list element name"),
new ArgumentDescriptor(ARG_ITEM_ELEMENT, ArgumentDescriptor.TYPE_STRING, "item element name")
};
}
@Override
public String getDescription() {
// TODO Auto-generated method stub
return "Indent list items";
}
}