1 11 12 package org.eclipse.ui.internal.console; 13 14 15 import java.util.ArrayList ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 19 import org.eclipse.jface.text.BadLocationException; 20 import org.eclipse.jface.text.Document; 21 import org.eclipse.jface.text.DocumentEvent; 22 import org.eclipse.jface.text.IDocument; 23 import org.eclipse.jface.text.IDocumentPartitioner; 24 import org.eclipse.jface.text.IDocumentPartitionerExtension; 25 import org.eclipse.jface.text.IRegion; 26 import org.eclipse.jface.text.ITypedRegion; 27 import org.eclipse.jface.text.Region; 28 import org.eclipse.swt.widgets.Display; 29 import org.eclipse.ui.console.ConsolePlugin; 30 import org.eclipse.ui.console.IConsoleManager; 31 import org.eclipse.ui.console.MessageConsoleStream; 32 33 38 public class MessageConsolePartitioner implements IDocumentPartitioner, IDocumentPartitionerExtension { 39 40 43 private IDocument fDocument = null; 44 45 48 private List fPartitions = new ArrayList (5); 49 50 53 private MessageConsoleStream fLastStream = null; 54 55 56 private int highWaterMark = 100000; 57 private int lowWaterMark = 80000; 58 private int maxAppendSize = lowWaterMark; 59 60 private List streamEntries = new ArrayList (); 61 private boolean killed = false; 62 private boolean updaterThreadStarted = false; 63 64 private IConsoleManager fConsoleManager; 65 69 public MessageConsolePartitioner() { 70 IDocument doc = new Document(); 71 connect(doc); 72 } 73 74 80 public void setWaterMarks(int low, int high) { 81 if (low >= high) { 82 throw new IllegalArgumentException (ConsoleMessages.getString("MessageConsolePartitioner.2")); } 84 if (low < 1000) { 85 throw new IllegalArgumentException (ConsoleMessages.getString("MessageConsolePartitioner.3")); } 87 lowWaterMark = low; 88 highWaterMark = high; 89 maxAppendSize = Math.min(80000, low); 90 } 91 94 public int getHighWaterMark() { 95 return highWaterMark; 96 } 97 98 101 public int getLowWaterMark() { 102 return lowWaterMark; 103 } 104 105 108 public int getMaxAppendSize() { 109 return maxAppendSize; 110 } 111 112 115 public void setMaxAppendSize(int maxAppendSize) { 116 this.maxAppendSize = maxAppendSize; 117 } 118 119 120 123 public void connect(IDocument document) { 124 fDocument = document; 125 document.setDocumentPartitioner(this); 126 fConsoleManager = ConsolePlugin.getDefault().getConsoleManager(); 127 } 128 129 132 public void disconnect() { 133 fDocument.setDocumentPartitioner(null); 134 killed = true; 135 fConsoleManager = null; 136 } 137 138 141 public void documentAboutToBeChanged(DocumentEvent event) { 142 } 143 144 147 public boolean documentChanged(DocumentEvent event) { 148 return documentChanged2(event) != null; 149 } 150 151 154 public String [] getLegalContentTypes() { 155 return new String [] {MessageConsolePartition.MESSAGE_PARTITION_TYPE}; 156 } 157 158 161 public String getContentType(int offset) { 162 ITypedRegion partition = getPartition(offset); 163 if (partition != null) { 164 return partition.getType(); 165 } 166 return null; 167 } 168 169 172 public ITypedRegion[] computePartitioning(int offset, int length) { 173 if (offset == 0 && length == fDocument.getLength()) { 174 return (ITypedRegion[])fPartitions.toArray(new ITypedRegion[fPartitions.size()]); 175 } 176 int end = offset + length; 177 List list = new ArrayList (); 178 for (int i = 0; i < fPartitions.size(); i++) { 179 ITypedRegion partition = (ITypedRegion)fPartitions.get(i); 180 int partitionStart = partition.getOffset(); 181 int partitionEnd = partitionStart + partition.getLength(); 182 if ((offset >= partitionStart && offset <= partitionEnd) || 183 (offset < partitionStart && end >= partitionStart)) { 184 list.add(partition); 185 } 186 } 187 return (ITypedRegion[])list.toArray(new ITypedRegion[list.size()]); 188 } 189 190 193 public ITypedRegion getPartition(int offset) { 194 for (int i = 0; i < fPartitions.size(); i++) { 195 ITypedRegion partition = (ITypedRegion)fPartitions.get(i); 196 int start = partition.getOffset(); 197 int end = start + partition.getLength(); 198 if (offset >= start && offset < end) { 199 return partition; 200 } 201 } 202 return null; 203 } 204 205 208 public IRegion documentChanged2(DocumentEvent event) { 209 210 String text = event.getText(); 211 if (getDocument().getLength() == 0) { 212 fPartitions.clear(); 214 return new Region(0,0); 215 } 216 addPartition(new MessageConsolePartition(fLastStream, event.getOffset(), text.length())); 217 ITypedRegion[] affectedRegions = computePartitioning(event.getOffset(), text.length()); 218 if (affectedRegions.length == 0) { 219 return null; 220 } 221 if (affectedRegions.length == 1) { 222 return affectedRegions[0]; 223 } 224 int affectedLength = affectedRegions[0].getLength(); 225 for (int i = 1; i < affectedRegions.length; i++) { 226 ITypedRegion region = affectedRegions[i]; 227 affectedLength += region.getLength(); 228 } 229 230 return new Region(affectedRegions[0].getOffset(), affectedLength); 231 } 232 233 234 238 protected void checkOverflow() { 239 if (highWaterMark >= 0) { 240 if (fDocument.getLength() > highWaterMark) { 241 int overflow = fDocument.getLength() - lowWaterMark; 242 243 try { 244 int line = fDocument.getLineOfOffset(overflow); 245 int nextLineOffset = fDocument.getLineOffset(line+1); 246 overflow = nextLineOffset; 247 } catch (BadLocationException e1) { 248 } 249 250 List newParitions = new ArrayList (fPartitions.size()); 252 Iterator partitions = fPartitions.iterator(); 253 while (partitions.hasNext()) { 254 ITypedRegion region = (ITypedRegion) partitions.next(); 255 if (region instanceof MessageConsolePartition) { 256 MessageConsolePartition messageConsolePartition = (MessageConsolePartition)region; 257 258 ITypedRegion newPartition = null; 259 int offset = region.getOffset(); 260 if (offset < overflow) { 261 int endOffset = offset + region.getLength(); 262 if (endOffset < overflow) { 263 } else { 265 int length = endOffset - overflow; 267 newPartition = messageConsolePartition.createNewPartition(0, length); 268 } 269 } else { 270 newPartition = messageConsolePartition.createNewPartition(messageConsolePartition.getOffset()-overflow, messageConsolePartition.getLength()); 272 } 273 if (newPartition != null) { 274 newParitions.add(newPartition); 275 } 276 } 277 } 278 fPartitions = newParitions; 279 280 try { 282 fDocument.replace(0, overflow, ""); } catch (BadLocationException e) { 284 } 285 } 286 } 287 } 288 289 290 294 private MessageConsolePartition addPartition(MessageConsolePartition partition) { 295 if (fPartitions.isEmpty()) { 296 fPartitions.add(partition); 297 } else { 298 int index = fPartitions.size() - 1; 299 MessageConsolePartition last = (MessageConsolePartition)fPartitions.get(index); 300 if (last.canBeCombinedWith(partition)) { 301 partition = last.combineWith(partition); 303 fPartitions.set(index, partition); 304 } else { 305 fPartitions.add(partition); 307 } 308 } 309 return partition; 310 } 311 312 319 public IDocument getDocument() { 320 return fDocument; 321 } 322 323 326 private void startUpdaterThread() { 327 if (updaterThreadStarted) { 328 return; 329 } 330 331 updaterThreadStarted = true; 332 333 Runnable r = new Runnable () { 334 public void run() { 335 336 while(!killed && streamEntries.size()>0) { 337 synchronized(streamEntries) { 338 final StreamEntry streamEntry = (StreamEntry)streamEntries.get(0); 339 streamEntries.remove(0); 340 341 Runnable innerRunnable = new Runnable () { 342 public void run() { 343 fLastStream = streamEntry.stream; 344 try { 345 fDocument.replace(fDocument.getLength(), 0, streamEntry.text.toString()); 346 checkOverflow(); 347 fConsoleManager.warnOfContentChange(streamEntry.stream.getConsole()); 348 } catch (BadLocationException e) { 349 } 350 } 351 }; 352 Display display = ConsolePlugin.getStandardDisplay(); 353 if (display != null) { 354 display.asyncExec(innerRunnable); 355 } 356 357 try { 358 Thread.sleep(100); 361 } catch (InterruptedException e) { 362 } 363 } 364 } 365 updaterThreadStarted = false; 366 } 367 }; 368 369 new Thread (r, "MessageConsoleUpdaterThread").start(); } 371 372 378 public void appendToDocument(final String text, final MessageConsoleStream stream) { 379 int offset = 0; 380 int length = text.length(); 381 382 synchronized(streamEntries) { 383 if (streamEntries.size() > 0) { 385 StreamEntry streamEntry = (StreamEntry)streamEntries.get(streamEntries.size()-1); 386 if (streamEntry.stream == stream) { 387 int emptySpace = maxAppendSize - streamEntry.text.length(); 388 if (length <= emptySpace) { 389 streamEntry.text.append(text); 390 offset = length; 391 length = 0; 392 } else { 393 streamEntry.text.append(text.substring(offset, emptySpace)); 394 offset += emptySpace; 395 length -= emptySpace; 396 } 397 } 398 } 399 400 while (length > 0) { 402 int toCopy = Math.min(maxAppendSize, length); 403 String substring = text.substring(offset, offset+toCopy); 404 StreamEntry streamEntry = new StreamEntry(substring, stream); 405 streamEntries.add(streamEntry); 406 offset += toCopy; 407 length -= toCopy; 408 } 409 410 } 412 startUpdaterThread(); 413 } 414 415 private class StreamEntry { 416 MessageConsoleStream stream; 417 StringBuffer text; 418 419 StreamEntry(String text, MessageConsoleStream stream) { 420 this.stream = stream; 421 this.text = new StringBuffer (text); 422 } 423 } 424 } | Popular Tags |