61cf2c5c3845803a8c4fd3aa1a8e79db8e97c4ad
[idea/community.git] / python / educational-core / student / src / com / jetbrains / edu / learning / core / EduDocumentListener.java
1 package com.jetbrains.edu.learning.core;
2
3 import com.intellij.openapi.editor.Document;
4 import com.intellij.openapi.editor.event.DocumentAdapter;
5 import com.intellij.openapi.editor.event.DocumentEvent;
6 import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
7 import com.intellij.openapi.util.TextRange;
8 import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder;
9 import com.jetbrains.edu.learning.courseFormat.TaskFile;
10
11 import java.util.ArrayList;
12 import java.util.List;
13
14 /**
15  * Listens changes in study files and updates
16  * coordinates of all the windows in current task file
17  */
18 public class EduDocumentListener extends DocumentAdapter {
19   private final TaskFile myTaskFile;
20   private final boolean myTrackLength;
21   private final List<AnswerPlaceholderWrapper> myAnswerPlaceholders = new ArrayList<AnswerPlaceholderWrapper>();
22
23
24   public EduDocumentListener(TaskFile taskFile) {
25     myTaskFile = taskFile;
26     myTrackLength = true;
27   }
28
29   public EduDocumentListener(TaskFile taskFile, boolean trackLength) {
30     myTaskFile = taskFile;
31     myTrackLength = trackLength;
32   }
33
34   @Override
35   public void beforeDocumentChange(DocumentEvent e) {
36     if (!myTaskFile.isTrackChanges()) {
37       return;
38     }
39     myTaskFile.setHighlightErrors(true);
40     myAnswerPlaceholders.clear();
41     for (AnswerPlaceholder answerPlaceholder : myTaskFile.getAnswerPlaceholders()) {
42       int twStart = answerPlaceholder.getOffset();
43       int length = answerPlaceholder.getRealLength();
44       int twEnd = twStart + length;
45       myAnswerPlaceholders.add(new AnswerPlaceholderWrapper(answerPlaceholder, twStart, twEnd));
46     }
47   }
48
49   @Override
50   public void documentChanged(DocumentEvent e) {
51     if (!myTaskFile.isTrackChanges()) {
52       return;
53     }
54     if (myAnswerPlaceholders.isEmpty()) return;
55     if (e instanceof DocumentEventImpl) {
56       DocumentEventImpl event = (DocumentEventImpl)e;
57       Document document = e.getDocument();
58       int offset = e.getOffset();
59       int change = event.getNewLength() - event.getOldLength();
60       for (AnswerPlaceholderWrapper answerPlaceholderWrapper : myAnswerPlaceholders) {
61         int twStart = answerPlaceholderWrapper.getTwStart();
62         if (twStart > offset) {
63           twStart += change;
64         }
65         int twEnd = answerPlaceholderWrapper.getTwEnd();
66         if (twEnd >= offset) {
67           twEnd += change;
68         }
69         AnswerPlaceholder answerPlaceholder = answerPlaceholderWrapper.getAnswerPlaceholder();
70         int length = twEnd - twStart;
71         answerPlaceholder.setOffset(twStart);
72         if (myTrackLength) {
73           if (answerPlaceholder.getUseLength()) {
74             answerPlaceholder.setLength(length);
75           } else {
76             answerPlaceholder.setPossibleAnswer(document.getText(TextRange.create(twStart, twStart + answerPlaceholder.getRealLength())));
77           }
78         }
79       }
80     }
81   }
82
83   private static class AnswerPlaceholderWrapper {
84     public AnswerPlaceholder myAnswerPlaceholder;
85     public int myTwStart;
86     public int myTwEnd;
87
88     public AnswerPlaceholderWrapper(AnswerPlaceholder answerPlaceholder, int twStart, int twEnd) {
89       myAnswerPlaceholder = answerPlaceholder;
90       myTwStart = twStart;
91       myTwEnd = twEnd;
92     }
93
94     public int getTwStart() {
95       return myTwStart;
96     }
97
98     public int getTwEnd() {
99       return myTwEnd;
100     }
101
102     public AnswerPlaceholder getAnswerPlaceholder() {
103       return myAnswerPlaceholder;
104     }
105   }
106 }
107