23 package com.realtime.crossfire.jxclient.gui.log;
26 import java.awt.Color;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.Iterator;
30 import java.util.List;
31 import java.util.Objects;
32 import java.util.concurrent.CopyOnWriteArrayList;
33 import org.jetbrains.annotations.NotNull;
34 import org.jetbrains.annotations.Nullable;
63 private final List<Line>
lines =
new CopyOnWriteArrayList<>();
75 private final Object
sync =
new Object();
121 throw new IllegalArgumentException(
"maxLines="+
maxLines);
133 synchronized (
sync) {
148 synchronized (
sync) {
163 synchronized (
sync) {
177 final List<Line> removedLines;
178 synchronized (
sync) {
179 removedLines =
new ArrayList<>(
lines);
183 if (!removedLines.isEmpty()) {
185 listener.linesRemoved(removedLines);
200 synchronized (
sync) {
201 final int position =
lines.isEmpty() ? 0 :
lines.get(
lines.size()-1).getEndPosition();
207 listener.lineAdded();
216 synchronized (
sync) {
217 final int position =
lines.size() < 2 ? 0 :
lines.get(
lines.size()-2).getEndPosition();
219 final int lastIndex =
lines.size()-1;
221 lines.set(lastIndex, line);
225 listener.lineReplaced();
233 final List<Line> removedLines;
234 synchronized (
sync) {
240 int positionsRemoved = 0;
243 removedLines.add(line);
248 line.updatePosition(positionsRemoved);
251 if (!removedLines.isEmpty()) {
253 listener.linesRemoved(removedLines);
266 synchronized (
sync) {
267 return lines.get(line);
276 synchronized (
sync) {
287 public Iterable<Line>
lines(
final int line) {
288 assert Thread.holdsLock(
sync);
290 return Collections.unmodifiableList(
lines).subList(line,
lines.size());
291 }
catch (
final IndexOutOfBoundsException ignored) {
292 return Collections.emptyList();
301 synchronized (
sync) {
339 public boolean mergeLines(@NotNull
final String text,
final int type,
final int subtype, @Nullable
final Color color) {
368 synchronized (
sync) {
373 position = line.getEndPosition();
389 public void addTextSegment(@NotNull
final Line line, @NotNull
final String text,
final boolean bold,
final boolean italic,
final boolean underline, @NotNull
final FontID fontID, @NotNull
final Color color, @NotNull
final Color selectionColor) {
390 line.addTextSegment(
newTextSegment(text, bold, italic, underline, fontID, color, selectionColor));
405 protected abstract TextSegment newTextSegment(@NotNull
final String text,
final boolean bold,
final boolean italic,
final boolean underline, @NotNull
final FontID fontID, @NotNull
final Color color, @NotNull
final Color selectionColor);
416 for (
final TextSegment segment : line.segments()) {
417 if (y <= yLine+segment.getY()) {
418 if (y <= yLine+segment.getY()-segment.getHeight()) {
419 return segment.getPosition();
421 if (x <= segment.getX()+segment.getWidth()) {
422 final int length = segment.getText().length();
423 for (
int i = 0; i < length; i++) {
425 if (x < segment.getX()+width) {
426 return segment.getPosition()+i;
429 return segment.getPosition()+length;
434 yLine += line.getHeight();
436 return lines.isEmpty() ? 0 :
lines.get(
lines.size()-1).getEndPosition();
454 public String
getText(
final int beginSelection,
final int endSelection) {
455 if (beginSelection >= endSelection) {
460 synchronized (
sync) {
464 while (i <
lines.size()) {
471 final StringBuilder sb =
new StringBuilder();
472 while (i <
lines.size()) {
478 if (sb.length() > 0) {
485 return sb.toString();