/* * Copyright 2008, Plutext Pty Ltd. * * This file is part of Docx4all. Docx4all is free software: you can redistribute it and/or modify it under the terms of version 3 of the GNU General Public License as published by the Free Software Foundation. Docx4all 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 Docx4all. If not, see <http://www.gnu.org/licenses/>. */ package org.plutext.client.wrappedTransforms; import java.util.HashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.docx4all.swing.text.DocumentElement; import org.docx4all.swing.text.WordMLDocument; import org.docx4all.xml.ElementML; import org.docx4all.xml.SdtBlockML; import org.plutext.client.Mediator; import org.plutext.client.Util; import org.plutext.client.state.StateChunk; import org.plutext.transforms.Changesets.Changeset; import org.plutext.transforms.Transforms.T; public class TransformMove extends TransformAbstract { private static Logger log = LoggerFactory.getLogger(TransformMove.class); public TransformMove(T t) { super(t); } String idref; @Override public String getPlutextId() { // Transmitting if (sdtWrapper!=null) { return sdtWrapper.getPlutextId(); } // Receiving if (idref ==null) { idref = Long.toString(t.getIdref() ); } return idref; } /* Compare the updated sdt to the original, replacing the * updated one with containing w:ins and w:del */ @Override public String markupChanges(String original, Changeset changeset) { // Do nothing. // How best to indicate to the user that something // has moved? Just in a dialog box? return null; } public long apply(Mediator mediator, HashMap<String, StateChunk> stateChunks) { String plutextId = getPlutextId(); log.debug("apply(): Moving SdtBlock = " + getSdt() + " - ID=" + plutextId); Long moveToIndex = null; if (this.t.getPosition() == null || this.t.getPosition() < 0) { log.error("apply(): Invalid location t.getPosition()=" + t.getPosition()); moveToIndex = null; } else { // if user has locally inserted/deleted sdt's // we need to adjust the specified position ... Long pos = t.getPosition(); moveToIndex = pos + mediator.getDivergences().getOffset(pos); log.debug("apply(): Location " + pos + " adjusted to " + moveToIndex); } if (moveToIndex == null || moveToIndex < 0) { log.error("apply(): Invalid moveToIndex=" + moveToIndex); // TODO - throw error return -1; } WordMLDocument doc = (WordMLDocument) mediator.getWordMLTextPane().getDocument(); DocumentElement elem = Util.getDocumentElement(doc, plutextId); if (elem == null) { // should not happen. log.error("apply(): DocumentElement NOT FOUND. Sdt Plutext Id=" + plutextId); // TODO - throw error return -1; } log.debug("apply(): DocumentElement of Sdt Plutext Id=" + plutextId + " is " + elem); DocumentElement root = (DocumentElement) doc.getDefaultRootElement(); ElementML bodyML = root.getElementML().getChild(0); int idx = Math.min(bodyML.getChildrenCount() - 1, moveToIndex.intValue()); log.debug("apply(): Maximum Index=" + (bodyML.getChildrenCount() - 1) + ". SdtBlock will be moved to idx=" + idx); ElementML elemMLAtMoveToIndex = bodyML.getChild(idx); log.debug("apply(): Currently, ElementML at idx=" + idx + " is " + elemMLAtMoveToIndex); if (elemMLAtMoveToIndex instanceof SdtBlockML) { SdtBlockML sdtML = (SdtBlockML) elemMLAtMoveToIndex; if (sdtML.getSdtProperties().getPlutextId().equals(getPlutextId() )) { log.debug("apply(): Need not to move." + " moveToIndex == currentIndex == " + idx); return sequenceNumber; } } // Semantics of move are // 1 remove existing element // 2 insert new element // So mediator.getDivergences().delete(plutextId); mediator.getDivergences().insert(plutextId, moveToIndex); //Move SdtBlock by first deleting the block. SdtBlockML copy = (SdtBlockML) elem.getElementML().clone(); elem.getElementML().delete(); updateRefreshOffsets(mediator, elem.getStartOffset(), elem.getEndOffset()); //Insert the deleted block into new position. elemMLAtMoveToIndex.addSibling(copy, false); //Record the offset range for the insertion just done. elem = (DocumentElement) root.getElement(idx); if (elem.getElementML() != elemMLAtMoveToIndex) { updateRefreshOffsets(mediator, 0, doc.getLength()); } else { updateRefreshOffsets(mediator, elem.getStartOffset(), elem.getEndOffset()); } return sequenceNumber; } }// TransformMove class