You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

IRCDocument.java 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. * Copyright (c) 2006-2017 DMDirc Developers
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
  5. * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
  6. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
  7. * permit persons to whom the Software is furnished to do so, subject to the following conditions:
  8. *
  9. * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
  10. * Software.
  11. *
  12. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  13. * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
  14. * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  15. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  16. */
  17. package com.dmdirc.ui.messages;
  18. import com.dmdirc.events.DisplayPropertyMap;
  19. import com.dmdirc.config.provider.AggregateConfigProvider;
  20. import com.dmdirc.config.provider.ConfigChangeListener;
  21. import com.dmdirc.util.collections.ListenerList;
  22. import java.awt.Font;
  23. import java.io.Serializable;
  24. import java.time.LocalDateTime;
  25. import java.util.ArrayList;
  26. import java.util.List;
  27. import javax.swing.UIManager;
  28. /**
  29. * Data contained in a TextPane.
  30. */
  31. public class IRCDocument implements Serializable, ConfigChangeListener, Document {
  32. /** A version number for this class. */
  33. private static final long serialVersionUID = 4;
  34. /** List of lines of text. */
  35. private final List<Line> lines;
  36. /** Listener list. */
  37. private final ListenerList listeners;
  38. /** Config Manager for getting settings. */
  39. private final AggregateConfigProvider configManager;
  40. /** This document's styliser. */
  41. private final Styliser styliser;
  42. /** Font size. */
  43. private int fontSize;
  44. /** Font name. */
  45. private String fontName;
  46. /** Frame buffer size. */
  47. private Integer frameBufferSize;
  48. public IRCDocument(final AggregateConfigProvider configManager, final Styliser styliser) {
  49. this.configManager = configManager;
  50. this.styliser = styliser;
  51. lines = new ArrayList<>();
  52. listeners = new ListenerList();
  53. frameBufferSize = configManager.getOptionInt("ui", "frameBufferSize", false);
  54. configManager.addChangeListener("ui", "textPaneFontSize", this);
  55. configManager.addChangeListener("ui", "textPaneFontName", this);
  56. configManager.addChangeListener("ui", "frameBufferSize", this);
  57. setCachedSettings();
  58. }
  59. @Override
  60. public int getNumLines() {
  61. synchronized (lines) {
  62. return lines.size();
  63. }
  64. }
  65. @Override
  66. public Line getLine(final int lineNumber) {
  67. synchronized (lines) {
  68. return lines.get(lineNumber);
  69. }
  70. }
  71. @Override
  72. public void addText(final LocalDateTime timestamp, final DisplayPropertyMap displayPropertyMap,
  73. final String text) {
  74. final int start;
  75. synchronized (lines) {
  76. start = lines.size();
  77. lines.add(new IRCLine(styliser, formatTimestamp(timestamp), text, displayPropertyMap,
  78. fontSize, fontName));
  79. }
  80. fireLinesAdded(start, 1);
  81. }
  82. private String formatTimestamp(final LocalDateTime timestamp) {
  83. return Formatter.formatMessage(configManager, "timestamp", timestamp);
  84. }
  85. @Override
  86. public void trim(final int numLines) {
  87. synchronized (lines) {
  88. if (frameBufferSize != null && frameBufferSize > 0) {
  89. final int i = lines.size() - numLines;
  90. if (i > 0) {
  91. lines.subList(0, i).clear();
  92. fireTrimmed(numLines, i);
  93. }
  94. }
  95. }
  96. }
  97. @Override
  98. public void clear() {
  99. synchronized (lines) {
  100. lines.clear();
  101. }
  102. fireCleared();
  103. }
  104. @Override
  105. public void addIRCDocumentListener(final DocumentListener listener) {
  106. if (listener == null) {
  107. return;
  108. }
  109. listeners.add(DocumentListener.class, listener);
  110. }
  111. @Override
  112. public void removeIRCDocumentListener(final DocumentListener listener) {
  113. listeners.remove(DocumentListener.class, listener);
  114. }
  115. /**
  116. * Fires the lines added method on all listeners.
  117. *
  118. * @param index Index of the added line
  119. * @param size Number of lines added
  120. */
  121. protected void fireLinesAdded(final int index, final int size) {
  122. for (DocumentListener listener
  123. : listeners.get(DocumentListener.class)) {
  124. listener.linesAdded(index, size, lines.size());
  125. }
  126. trim(frameBufferSize);
  127. }
  128. /**
  129. * Fires the trimmed method on all listeners.
  130. *
  131. * @param newSize New document size
  132. * @param trimmedLines Number of trimmed lines
  133. */
  134. protected void fireTrimmed(final int newSize, final int trimmedLines) {
  135. for (DocumentListener listener
  136. : listeners.get(DocumentListener.class)) {
  137. listener.trimmed(newSize, trimmedLines);
  138. }
  139. }
  140. /**
  141. * fires the cleared method on all listeners.
  142. */
  143. protected void fireCleared() {
  144. listeners.get(DocumentListener.class).forEach(DocumentListener::cleared);
  145. }
  146. /**
  147. * fires the need repaint method on all listeners.
  148. */
  149. protected void fireRepaintNeeded() {
  150. listeners.get(DocumentListener.class).forEach(DocumentListener::repaintNeeded);
  151. }
  152. /**
  153. * Returns the line height of the specified line.
  154. *
  155. * @param line Line
  156. *
  157. * @return Line height
  158. */
  159. protected int getLineHeight(final Line line) {
  160. return line.getFontSize();
  161. }
  162. @Override
  163. public int getLineHeight(final int line) {
  164. return getLineHeight(getLine(line));
  165. }
  166. /**
  167. * Sets all the cached settings in this document.
  168. */
  169. private void setCachedSettings() {
  170. final Font defaultFont = UIManager.getFont("TextPane.font");
  171. if (configManager.hasOptionString("ui", "textPaneFontName")) {
  172. fontName = configManager.getOption("ui", "textPaneFontName");
  173. } else {
  174. fontName = defaultFont.getName();
  175. }
  176. if (configManager.hasOptionString("ui", "textPaneFontSize")) {
  177. fontSize = configManager.getOptionInt("ui", "textPaneFontSize");
  178. } else {
  179. fontSize = defaultFont.getSize();
  180. }
  181. frameBufferSize = configManager.getOptionInt("ui", "frameBufferSize", true);
  182. trim(frameBufferSize);
  183. }
  184. @Override
  185. public void configChanged(final String domain, final String key) {
  186. setCachedSettings();
  187. synchronized (lines) {
  188. for (Line line : lines) {
  189. line.setFontName(fontName);
  190. line.setFontSize(fontSize);
  191. }
  192. }
  193. fireRepaintNeeded();
  194. }
  195. }