View Javadoc

1   /*
2    * Copyright 1999-2006 Faculty of Mathematics, Physics
3    * and Informatics, Comenius University, Bratislava. This file is protected by
4    * the Mozilla Public License version 1.1 (the License); you may not use this
5    * file except in compliance with the License. You may obtain a copy of the
6    * License at http://euromath2.sourceforge.net/license.html Unless required by
7    * applicable law or agreed to in writing, software distributed under the
8    * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
9    * OF ANY KIND, either express or implied. See the License for the specific
10   * language governing permissions and limitations under the License.
11   */
12  package sk.uniba.euromath.editor.textEditor.policies;
13  
14  import java.util.ArrayList;
15  import java.util.List;
16  
17  import org.eclipse.gef.EditPart;
18  import org.eclipse.gef.Request;
19  import org.eclipse.gef.commands.Command;
20  import org.eclipse.swt.SWT;
21  
22  import sk.uniba.euromath.document.XMLAccess;
23  import sk.uniba.euromath.editor.textEditor.CaretManager;
24  import sk.uniba.euromath.editor.textEditor.ITextPieceKeeper;
25  import sk.uniba.euromath.editor.textEditor.TextPieceInfoImpl;
26  import sk.uniba.euromath.editor.textEditor.commands.DeleteTextCommand;
27  import sk.uniba.euromath.editor.textEditor.commands.InsertTextCommand;
28  import sk.uniba.euromath.editor.textEditor.commands.SwitchEditModeCommand;
29  import sk.uniba.euromath.editor.textEditor.editParts.TextEditPart;
30  import sk.uniba.euromath.editor.textEditor.requests.IRequestSpecialization;
31  import sk.uniba.euromath.editor.textEditor.requests.RequestConstants;
32  import sk.uniba.euromath.editor.textEditor.requests.RetargetCaretRequest;
33  import sk.uniba.euromath.editor.textEditor.requests.caretRequests.DeactivateCaretRequest;
34  import sk.uniba.euromath.editor.textEditor.requests.editTextRequests.ActivateTextEditingRequest;
35  import sk.uniba.euromath.editor.textEditor.requests.editTextRequests.DeleteTextRequest;
36  import sk.uniba.euromath.editor.textEditor.requests.editTextRequests.InsertTextRequest;
37  import sk.uniba.euromath.editor.textEditor.requests.editTextRequests.DeleteTextRequest.DeleteInfo;
38  
39  /***
40   * Policy for handling requests to edit piece of text managed by piece keeper
41   * and activation of text editing.
42   * 
43   * @author Tomáš Studva, Martin Kollar 30.9.2005
44   */
45  public class TextEditPolicy extends AbstractTextEditPolicy {
46  
47      /***
48       * Manager that cares about Caret.
49       */
50      private CaretManager caretManager;
51  
52      /***
53       * XMLAccess instance.
54       */
55      private final XMLAccess xmlAccess;
56  
57      /***
58       * Constructor.
59       * 
60       * @param xmlAccess
61       *            access to XML data
62       * @param cManager CaretManager
63       */
64      public TextEditPolicy(XMLAccess xmlAccess, CaretManager cManager) {
65          super();
66          this.xmlAccess = xmlAccess;
67          caretManager = cManager;
68      }
69  
70      /***
71       * Creates SwitchEditModeCommand as response to ActivateTextEditingRequest.
72       * 
73       * @param req
74       *            for activation of text editing
75       * @return command able to activate text editing
76       */
77      protected Command createActivationCommand(ActivateTextEditingRequest req) {
78          SwitchEditModeCommand cmd = new SwitchEditModeCommand(req.getSource(),
79                  req.getCaretOffset(), caretManager, req.getDomain());
80          return cmd;
81      }
82  
83      /***
84       * Creates InsertTextCommand as response to InsertTextRequest.
85       * 
86       * @param request
87       *            for insertion of text
88       * @return command able to execute insertion of text
89       */
90      protected Command createInsertTextCommand(InsertTextRequest request) {
91  
92          return new InsertTextCommand(request.getDestination(), request
93                  .getOffset(), request.getText(), getXmlAccess());
94      }
95  
96      /***
97       * Creates TextDeleteCommand as response to DeleteTextRequest.
98       * 
99       * @param req
100      *            request to delete text
101      * @return command able to delete text
102      */
103     protected Command createTextDeleteCommand(DeleteTextRequest req) {
104         int size = req.getSize(); // size of deletion
105         int offset = req.getOffset();
106         List<DeleteInfo> delInfo = req.getStructuredDeleteInfo();
107 
108         // direction is left
109         if (size < 0) {
110             size = -size;
111             // if deletion is within host's text
112             if (0 <= offset - size + 1) {
113                 // 1, create ids to delete
114                 List<String> ids = new ArrayList<String>();
115                 // add first id that deletes text in this's host
116                 ids.add(TextPieceInfoImpl.buildID(TextPieceInfoImpl
117                         .getParsedNodeId(getHost().getID()), getHost()
118                         .getTextPieceInfo().getOriginalOffset()
119                         + offset - size, size));
120                 for (DeleteInfo deleteInfo : delInfo) {
121                     ids.add(TextPieceInfoImpl.buildID(deleteInfo.pieceKeeper
122                             .getTextPieceInfo().getNodeID(), deleteInfo.start,
123                             deleteInfo.length));
124                 }
125                 // 2, tidy up ids
126                 TextPieceInfoImpl.tidyUpIds(ids);
127                 // 3, create compound command
128                 return DeleteTextCommand.createCommandToDeleteText(ids,
129                         getXmlAccess());
130             }
131             // if deletion is within host's text and text before host's text
132             // find previous host
133             RetargetCaretRequest request = new RetargetCaretRequest(getHost(),
134                     SWT.ARROW_LEFT, ' ', false, getHost().getTextLocator()
135                             .getBounds().getTopRight(), 0);
136             EditPart prevPart = getHost().getTargetEditPart(request);
137             if ((prevPart == getHost())
138                     || !(prevPart instanceof ITextPieceKeeper))
139                 throw new IllegalStateException("Next part is invalid."); //$NON-NLS-1$
140             // delegate command creation to previous host by sending
141             // TextDeleteRequest with partly restructured delete info - tail
142             // recursion with accumulator
143             delInfo.add(req.new DeleteInfo(getHost(), 0, offset + 1));
144             // TODO set source?
145             ITextPieceKeeper keeper = (ITextPieceKeeper) prevPart;
146             req.setOffset(keeper.getText().length() - 1);
147             req.setSize(-(size - offset - 1));
148             return prevPart.getCommand(req);
149         }
150         // direction is right
151         if (size > 0) {
152             // if deletion is within host's text
153             // offset + size - 1 <= getHost().getText().length() - 1
154             if (offset + size <= getHost().getText().length()) {
155                 // 1, create ids to delete
156                 List<String> ids = new ArrayList<String>();
157                 // add first that deletes text in this's host
158                 ids.add(TextPieceInfoImpl.buildID(TextPieceInfoImpl
159                         .getParsedNodeId(getHost().getID()), getHost()
160                         .getTextPieceInfo().getOriginalOffset()
161                         + offset + size - 1, size));
162                 for (DeleteInfo deleteInfo : delInfo) {
163                     ids.add(TextPieceInfoImpl.buildID(deleteInfo.pieceKeeper
164                             .getTextPieceInfo().getNodeID(), deleteInfo.start,
165                             deleteInfo.length));
166                 }
167                 // 2, tidy up ids
168                 TextPieceInfoImpl.tidyUpIds(ids);
169                 // 3, create compound command
170                 return DeleteTextCommand.createCommandToDeleteText(ids,
171                         getXmlAccess());
172             }
173             // if deletion is within host's text and text after host's text
174             // find next host
175             RetargetCaretRequest request = new RetargetCaretRequest(getHost(),
176                     SWT.ARROW_RIGHT, ' ', false, getHost().getTextLocator()
177                             .getBounds().getTopLeft(), getHost().getText()
178                             .length() - 1);
179             EditPart nextPart = getHost().getTargetEditPart(request);
180             if ((nextPart == getHost())
181                     || !(nextPart instanceof ITextPieceKeeper))
182                 throw new IllegalStateException("Next part is invalid."); //$NON-NLS-1$
183             // delegate command creation to next host by sending
184             // TextDeleteRequest with partly restructured delete info - tail
185             // recursion with accumulator
186             delInfo.add(req.new DeleteInfo(getHost(), offset, getHost()
187                     .getText().length()
188                     - 1 - offset));
189             // TODO set source?
190             // ITextPieceKeeper keeper = (ITextPieceKeeper) nextPart;
191             req.setOffset(0);
192             req.setSize(size - getHost().getText().length() + 1 + offset);
193             return nextPart.getCommand(req);
194         }
195         return null; // size == 0, illegal
196 
197     }
198 
199     /***
200      * @see org.eclipse.gef.EditPolicy#getCommand(org.eclipse.gef.Request)
201      * 
202      * @return SwitchEditModeCommand or TextInputCommand or DeleteTextCommand or
203      *         null
204      */
205     @Override
206     public Command getCommand(Request request) {
207         Object type = request.getType();
208 
209         if (RequestConstants.EDIT_TEXT_REQUEST.equals(type)) {
210             IRequestSpecialization req = (IRequestSpecialization) request;
211 
212             if (req.getSpecialization() == RequestConstants.ACTIVATE_TEXT_EDITING_REQUEST)
213                 return createActivationCommand((ActivateTextEditingRequest) req);
214 
215             if (req.getSpecialization() == RequestConstants.INSERT_TEXT_REQUEST)
216                 return createInsertTextCommand((InsertTextRequest) req);
217 
218             if (req.getSpecialization() == RequestConstants.DELETE_TEXT_REQUEST) {
219                 getHost().performRequest(new DeactivateCaretRequest());
220                 return createTextDeleteCommand((DeleteTextRequest) req);
221             }
222         }
223 
224         return null;
225     }
226 
227 
228     @Override
229     /***
230      * 
231      * @return the <i>host</i> EditPart on which this policy is installed.
232      */
233     public TextEditPart getHost() {
234         return (TextEditPart) super.getHost();
235     }
236 
237     /***
238      * @see org.eclipse.gef.EditPolicy#getTargetEditPart(org.eclipse.gef.Request)
239      * 
240      * @return host if understands the request else returns <code>null</code>
241      */
242     @Override
243     public EditPart getTargetEditPart(Request request) {
244         if (understandsRequest(request))
245             return getHost();
246 
247         return super.getTargetEditPart(request);
248     }
249 
250     /***
251      * @return Returns the xmlAccess.
252      */
253     protected XMLAccess getXmlAccess() {
254         return this.xmlAccess;
255     }
256 
257 }