1 11 12 package org.eclipse.jface.text; 13 14 15 import java.util.ArrayList ; 16 import java.util.Collections ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 import java.util.ListIterator ; 20 import java.util.NoSuchElementException ; 21 22 import org.eclipse.swt.events.VerifyEvent; 23 24 import org.eclipse.core.runtime.Assert; 25 26 27 36 public class DocumentCommand { 37 38 42 private static class Command implements Comparable { 43 44 private final int fOffset; 45 46 private final int fLength; 47 48 private final String fText; 49 50 private final IDocumentListener fOwner; 51 52 61 public Command(int offset, int length, String text, IDocumentListener owner) { 62 if (offset < 0 || length < 0) 63 throw new IllegalArgumentException (); 64 fOffset= offset; 65 fLength= length; 66 fText= text; 67 fOwner= owner; 68 } 69 70 75 public int getDeltaLength() { 76 return (fText == null ? 0 : fText.length()) - fLength; 77 } 78 79 85 public void execute(IDocument document) throws BadLocationException { 86 87 if (fLength == 0 && fText == null) 88 return; 89 90 if (fOwner != null) 91 document.removeDocumentListener(fOwner); 92 93 document.replace(fOffset, fLength, fText); 94 95 if (fOwner != null) 96 document.addDocumentListener(fOwner); 97 } 98 99 102 public int compareTo(final Object object) { 103 if (isEqual(object)) 104 return 0; 105 106 final Command command= (Command) object; 107 108 if (fOffset + fLength <= command.fOffset || command.fOffset + command.fLength <= fOffset) { 110 int value= (2 * fOffset + fLength) - (2 * command.fOffset + command.fLength); 111 if (value != 0) 112 return value; 113 } 114 return 42; 116 } 117 118 private boolean isEqual(Object object) { 119 if (object == this) 120 return true; 121 if (! (object instanceof Command)) 122 return false; 123 final Command command= (Command) object; 124 return command.fOffset == fOffset && command.fLength == fLength; 125 } 126 } 127 128 131 private static class ReverseListIterator implements Iterator { 132 133 134 private final ListIterator fListIterator; 135 136 140 public ReverseListIterator(ListIterator listIterator) { 141 if (listIterator == null) 142 throw new IllegalArgumentException (); 143 fListIterator= listIterator; 144 } 145 146 149 public boolean hasNext() { 150 return fListIterator.hasPrevious(); 151 } 152 153 156 public Object next() { 157 return fListIterator.previous(); 158 } 159 160 163 public void remove() { 164 throw new UnsupportedOperationException (); 165 } 166 } 167 168 171 private static class CommandIterator implements Iterator { 172 173 174 private final Iterator fIterator; 175 176 177 private Command fCommand; 178 179 180 private boolean fForward; 181 182 189 public CommandIterator(final List commands, final Command command, final boolean forward) { 190 if (commands == null || command == null) 191 throw new IllegalArgumentException (); 192 fIterator= forward ? commands.iterator() : new ReverseListIterator(commands.listIterator(commands.size())); 193 fCommand= command; 194 fForward= forward; 195 } 196 197 200 public boolean hasNext() { 201 return fCommand != null || fIterator.hasNext(); 202 } 203 204 207 public Object next() { 208 209 if (! hasNext()) 210 throw new NoSuchElementException (); 211 212 if (fCommand == null) 213 return fIterator.next(); 214 215 if (!fIterator.hasNext()) { 216 final Command tempCommand= fCommand; 217 fCommand= null; 218 return tempCommand; 219 } 220 221 final Command command= (Command) fIterator.next(); 222 final int compareValue= command.compareTo(fCommand); 223 224 if ((compareValue < 0) ^ ! fForward) { 225 return command; 226 227 } else if ((compareValue > 0) ^ ! fForward) { 228 final Command tempCommand= fCommand; 229 fCommand= command; 230 return tempCommand; 231 232 } else { 233 throw new IllegalArgumentException (); 234 } 235 } 236 237 240 public void remove() { 241 throw new UnsupportedOperationException (); 242 } 243 } 244 245 246 public boolean doit= false; 247 248 public int offset; 249 250 public int length; 251 252 public String text; 253 257 public IDocumentListener owner; 258 262 public int caretOffset; 263 267 private final List fCommands= new ArrayList (); 268 272 public boolean shiftsCaret; 273 274 275 278 protected DocumentCommand() { 279 } 280 281 287 void setEvent(VerifyEvent event, IRegion modelRange) { 288 289 doit= true; 290 text= event.text; 291 292 offset= modelRange.getOffset(); 293 length= modelRange.getLength(); 294 295 owner= null; 296 caretOffset= -1; 297 shiftsCaret= true; 298 fCommands.clear(); 299 } 300 301 310 boolean fillEvent(VerifyEvent event, IRegion modelRange) { 311 event.text= text; 312 event.doit= (offset == modelRange.getOffset() && length == modelRange.getLength() && doit && caretOffset == -1); 313 return event.doit; 314 } 315 316 328 public void addCommand(int commandOffset, int commandLength, String commandText, IDocumentListener commandOwner) throws BadLocationException { 329 final Command command= new Command(commandOffset, commandLength, commandText, commandOwner); 330 331 if (intersects(command)) 332 throw new BadLocationException(); 333 334 final int index= Collections.binarySearch(fCommands, command); 335 336 if (index >= 0) 338 throw new BadLocationException(); 339 340 final int insertionIndex= -(index + 1); 342 343 if (insertionIndex != fCommands.size() && intersects((Command) fCommands.get(insertionIndex), command)) 345 throw new BadLocationException(); 346 347 if (insertionIndex != 0 && intersects((Command) fCommands.get(insertionIndex - 1), command)) 349 throw new BadLocationException(); 350 351 fCommands.add(insertionIndex, command); 352 } 353 354 361 public Iterator getCommandIterator() { 362 Command command= new Command(offset, length, text, owner); 363 return new CommandIterator(fCommands, command, true); 364 } 365 366 372 public int getCommandCount() { 373 return 1 + fCommands.size(); 374 } 375 376 384 private boolean intersects(Command command0, Command command1) { 385 if (command0.fOffset + command0.fLength <= command1.fOffset || command1.fOffset + command1.fLength <= command0.fOffset) 387 return (2 * command0.fOffset + command0.fLength) - (2 * command1.fOffset + command1.fLength) == 0; 388 return true; 389 } 390 391 398 private boolean intersects(Command command) { 399 if (offset + length <= command.fOffset || command.fOffset + command.fLength <= offset) 401 return (2 * offset + length) - (2 * command.fOffset + command.fLength) == 0; 402 return true; 403 } 404 405 412 void execute(IDocument document) throws BadLocationException { 413 414 if (length == 0 && text == null && fCommands.size() == 0) 415 return; 416 417 DefaultPositionUpdater updater= new DefaultPositionUpdater(getCategory()); 418 Position caretPosition= null; 419 try { 420 if (updateCaret()) { 421 document.addPositionCategory(getCategory()); 422 document.addPositionUpdater(updater); 423 caretPosition= new Position(caretOffset); 424 document.addPosition(getCategory(), caretPosition); 425 } 426 427 final Command originalCommand= new Command(offset, length, text, owner); 428 for (final Iterator iterator= new CommandIterator(fCommands, originalCommand, false); iterator.hasNext(); ) 429 ((Command) iterator.next()).execute(document); 430 431 } catch (BadLocationException e) { 432 } catch (BadPositionCategoryException e) { 434 } finally { 436 if (updateCaret()) { 437 document.removePositionUpdater(updater); 438 try { 439 document.removePositionCategory(getCategory()); 440 } catch (BadPositionCategoryException e) { 441 Assert.isTrue(false); 442 } 443 caretOffset= caretPosition.getOffset(); 444 } 445 } 446 } 447 448 454 private boolean updateCaret() { 455 return shiftsCaret && caretOffset != -1; 456 } 457 458 464 private String getCategory() { 465 return toString(); 466 } 467 468 } 469 | Popular Tags |