PageRenderTime 55ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/bundles/plugins-trunk/RubyPlugin/src/org/jedit/ruby/structure/BufferChangeHandler.java

#
Java | 227 lines | 163 code | 42 blank | 22 comment | 28 complexity | 6474e524d0db7c78970c2f4a545bb81b MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * BufferChangeHandler.java -
  3. *
  4. * Copyright 2005 Robert McKinnon
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. package org.jedit.ruby.structure;
  21. import org.gjt.sp.jedit.buffer.BufferAdapter;
  22. import org.gjt.sp.jedit.Buffer;
  23. import org.gjt.sp.jedit.View;
  24. import org.gjt.sp.jedit.jEdit;
  25. import org.gjt.sp.jedit.textarea.JEditTextArea;
  26. import org.jedit.ruby.RubyPlugin;
  27. import org.jedit.ruby.utils.EditorView;
  28. import java.util.*;
  29. import java.util.List;
  30. import java.awt.*;
  31. /**
  32. * @author robmckinnon at users.sourceforge.net
  33. */
  34. public class BufferChangeHandler extends BufferAdapter {
  35. private static final BufferChangeHandler instance = new BufferChangeHandler();
  36. private final Map<String, Map<Integer, Edit>> fileToEdit = new HashMap<String, Map<Integer, Edit>>();
  37. private final List<Edit> allEdits = new ArrayList<Edit>();
  38. private boolean previousEditAction;
  39. private int editLocationIndex = 0;
  40. private BufferChangeHandler() {
  41. }
  42. public static BufferChangeHandler instance() {
  43. return instance;
  44. }
  45. public void preContentRemoved(Buffer buffer, int startLine, int offset, int numLines, int length) {
  46. }
  47. public void transactionComplete(Buffer buffer) {
  48. EditorView view = RubyPlugin.getActiveView();
  49. int line = view.getLineAtCaret();
  50. Map<Integer, Edit> lineEdits = getLineEdits(buffer.getPath());
  51. if (lineEdits.containsKey(line)) {
  52. lineEdits.get(line).offsetInLine = view.getCaretOffsetInLine();
  53. }
  54. }
  55. public void contentInserted(Buffer buffer, int startLine, int offset, int numLines, int length) {
  56. if (numLines > 0) {
  57. Map<Integer, Edit> lineEdits = getLineEdits(buffer.getPath());
  58. Collection<Edit> edits = new ArrayList<Edit>(lineEdits.values());
  59. for (Edit edit : edits) {
  60. if (edit.line >= startLine) {
  61. lineEdits.remove(edit.line);
  62. edit.incrementLine(numLines);
  63. lineEdits.put(edit.line, edit);
  64. }
  65. }
  66. }
  67. if (numLines == 0) {
  68. updateEdits(buffer, startLine, offset + length - buffer.getLineStartOffset(startLine));
  69. } else {
  70. updateEdits(buffer, startLine, offset - buffer.getLineStartOffset(startLine));
  71. }
  72. }
  73. public void contentRemoved(Buffer buffer, int startLine, int offset, int numLines, int length) {
  74. if (numLines > 0) {
  75. Map<Integer, Edit> lineEdits = getLineEdits(buffer.getPath());
  76. for (int line = startLine; line < startLine + numLines; line++) {
  77. Edit edit = lineEdits.remove(line);
  78. allEdits.remove(edit);
  79. }
  80. Collection<Edit> edits = new ArrayList<Edit>(lineEdits.values());
  81. for (Edit edit : edits) {
  82. if (edit.line >= startLine + numLines) {
  83. lineEdits.remove(edit.line);
  84. edit.decrement(numLines);
  85. lineEdits.put(edit.line, edit);
  86. }
  87. }
  88. }
  89. updateEdits(buffer, startLine, offset - buffer.getLineStartOffset(startLine));
  90. }
  91. private void updateEdits(Buffer buffer, int line, int offsetInLine) {
  92. String file = buffer.getPath();
  93. Edit edit = new Edit(file, line, offsetInLine);
  94. allEdits.remove(edit);
  95. allEdits.add(edit);
  96. Map<Integer, Edit> lineEdits = getLineEdits(file);
  97. lineEdits.put(line, edit);
  98. if (line > 0 && lineEdits.containsKey(line - 1)) {
  99. removeEditAt(line - 1, lineEdits);
  100. }
  101. if (line < (buffer.getLineCount() - 1) && lineEdits.containsKey(line + 1)) {
  102. removeEditAt(line + 1, lineEdits);
  103. }
  104. }
  105. private void removeEditAt(int line, Map<Integer, Edit> lineEdits) {
  106. Edit previousEdit = lineEdits.remove(line);
  107. allEdits.remove(previousEdit);
  108. }
  109. public void gotoPreviousEdit(View view) {
  110. setGotoPreviousEdit(true);
  111. if (!allEdits.isEmpty() && editLocationIndex < allEdits.size()) {
  112. editLocationIndex++;
  113. final Edit edit = allEdits.get(allEdits.size() - editLocationIndex);
  114. if (edit.file.equals(view.getBuffer().getPath())) {
  115. gotoEdit(view.getTextArea(), edit);
  116. } else {
  117. Buffer buffer = jEdit.openFile(view, edit.file);
  118. if (buffer != null) {
  119. view.goToBuffer(buffer);
  120. EventQueue.invokeLater(new Runnable() {
  121. public void run() {
  122. gotoEdit(jEdit.getActiveView().getTextArea(), edit);
  123. }
  124. });
  125. } else {
  126. setGotoPreviousEdit(false);
  127. }
  128. }
  129. } else {
  130. setGotoPreviousEdit(false);
  131. }
  132. }
  133. private void gotoEdit(JEditTextArea textArea, Edit edit) {
  134. textArea.setCaretPosition(edit.getEditOffset(textArea));
  135. setGotoPreviousEdit(false);
  136. }
  137. public boolean isGotoPreviousEditAction() {
  138. return previousEditAction;
  139. }
  140. public void resetEditLocationIndex() {
  141. editLocationIndex = 0;
  142. }
  143. public void setGotoPreviousEdit(boolean action) {
  144. previousEditAction = action;
  145. }
  146. private Map<Integer, Edit> getLineEdits(String file) {
  147. if (!fileToEdit.containsKey(file)) {
  148. Map<Integer, Edit> lineToEdit = new HashMap<Integer, Edit>();
  149. fileToEdit.put(file, lineToEdit);
  150. }
  151. return fileToEdit.get(file);
  152. }
  153. public static class Edit {
  154. String file;
  155. int line;
  156. int offsetInLine;
  157. public Edit(String file, int line, int offsetInLine) {
  158. this.file = file;
  159. this.line = line;
  160. this.offsetInLine = offsetInLine;
  161. }
  162. private int getEditOffset(JEditTextArea textArea) {
  163. if (line < textArea.getLineCount()) {
  164. String lineText = textArea.getLineText(line);
  165. int offsetInLineText = offsetInLine <= lineText.length() ? offsetInLine : lineText.length();
  166. return textArea.getLineStartOffset(line) + offsetInLineText;
  167. } else {
  168. return textArea.getText().length();
  169. }
  170. }
  171. public boolean equals(Object obj) {
  172. Edit edit = (Edit)obj;
  173. return file.equals(edit.file) && line == edit.line;
  174. }
  175. public int hashCode() {
  176. return file.hashCode() + line;
  177. }
  178. public void incrementLine(int numLines) {
  179. line += numLines;
  180. }
  181. public void decrement(int numLines) {
  182. line -= numLines;
  183. }
  184. }
  185. }