2 * Copyright 2000-2015 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.xdebugger.impl.ui;
18 import com.intellij.ide.DataManager;
19 import com.intellij.lang.Language;
20 import com.intellij.lang.LanguageUtil;
21 import com.intellij.openapi.actionSystem.AnAction;
22 import com.intellij.openapi.actionSystem.AnActionEvent;
23 import com.intellij.openapi.actionSystem.DataContext;
24 import com.intellij.openapi.actionSystem.DefaultActionGroup;
25 import com.intellij.openapi.editor.Document;
26 import com.intellij.openapi.editor.Editor;
27 import com.intellij.openapi.project.Project;
28 import com.intellij.openapi.ui.popup.JBPopupFactory;
29 import com.intellij.openapi.ui.popup.ListPopup;
30 import com.intellij.openapi.util.IconLoader;
31 import com.intellij.openapi.wm.IdeFocusManager;
32 import com.intellij.reference.SoftReference;
33 import com.intellij.ui.ClickListener;
34 import com.intellij.util.ui.JBUI;
35 import com.intellij.xdebugger.XDebuggerBundle;
36 import com.intellij.xdebugger.XExpression;
37 import com.intellij.xdebugger.XSourcePosition;
38 import com.intellij.xdebugger.evaluation.EvaluationMode;
39 import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
40 import com.intellij.xdebugger.impl.XDebuggerHistoryManager;
41 import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl;
42 import org.jetbrains.annotations.NonNls;
43 import org.jetbrains.annotations.NotNull;
44 import org.jetbrains.annotations.Nullable;
48 import java.awt.event.MouseEvent;
49 import java.lang.ref.WeakReference;
50 import java.util.Collection;
51 import java.util.Collections;
52 import java.util.List;
57 public abstract class XDebuggerEditorBase {
58 private final Project myProject;
59 private final XDebuggerEditorsProvider myDebuggerEditorsProvider;
60 @NotNull private final EvaluationMode myMode;
61 @Nullable private final String myHistoryId;
62 @Nullable private XSourcePosition mySourcePosition;
63 private int myHistoryIndex = -1;
65 private final JLabel myChooseFactory = new JLabel();
66 private WeakReference<ListPopup> myPopup;
68 protected XDebuggerEditorBase(final Project project,
69 @NotNull XDebuggerEditorsProvider debuggerEditorsProvider,
70 @NotNull EvaluationMode mode,
71 @Nullable @NonNls String historyId,
72 final @Nullable XSourcePosition sourcePosition) {
74 myDebuggerEditorsProvider = debuggerEditorsProvider;
76 myHistoryId = historyId;
77 mySourcePosition = sourcePosition;
79 myChooseFactory.setToolTipText(XDebuggerBundle.message("xdebugger.evaluate.language.hint"));
80 myChooseFactory.setBorder(JBUI.Borders.empty(0, 3, 0, 3));
83 public boolean onClick(@NotNull MouseEvent e, int clickCount) {
84 ListPopup oldPopup = SoftReference.dereference(myPopup);
85 if (oldPopup != null && !oldPopup.isDisposed()) {
90 ListPopup popup = createLanguagePopup();
91 popup.showUnderneathOf(myChooseFactory);
92 myPopup = new WeakReference<ListPopup>(popup);
95 }.installOn(myChooseFactory);
98 private ListPopup createLanguagePopup() {
99 DefaultActionGroup actions = new DefaultActionGroup();
100 for (final Language language : getEditorsProvider().getSupportedLanguages(myProject, mySourcePosition)) {
101 //noinspection ConstantConditions
102 actions.add(new AnAction(language.getDisplayName(), null, language.getAssociatedFileType().getIcon()) {
104 public void actionPerformed(@NotNull AnActionEvent e) {
105 XExpression currentExpression = getExpression();
106 setExpression(new XExpressionImpl(currentExpression.getExpression(), language, currentExpression.getCustomInfo()));
107 requestFocusInEditor();
112 DataContext dataContext = DataManager.getInstance().getDataContext(getComponent());
113 return JBPopupFactory.getInstance().createActionGroupPopup("Choose Language", actions, dataContext,
114 JBPopupFactory.ActionSelectionAid.SPEEDSEARCH,
118 protected JPanel addChooseFactoryLabel(JComponent component, boolean top) {
119 JPanel panel = new JPanel(new BorderLayout());
120 panel.add(component, BorderLayout.CENTER);
122 JPanel factoryPanel = new JPanel(new BorderLayout());
123 factoryPanel.add(myChooseFactory, top ? BorderLayout.NORTH : BorderLayout.CENTER);
124 panel.add(factoryPanel, BorderLayout.WEST);
128 public void setSourcePosition(@Nullable XSourcePosition sourcePosition) {
129 if (mySourcePosition != sourcePosition) {
130 mySourcePosition = sourcePosition;
131 setExpression(getExpression());
136 public EvaluationMode getMode() {
141 public abstract Editor getEditor();
143 public abstract JComponent getComponent();
145 public JComponent getEditorComponent() {
146 return getComponent();
149 protected abstract void doSetText(XExpression text);
151 public void setExpression(@Nullable XExpression text) {
153 text = getMode() == EvaluationMode.EXPRESSION ? XExpressionImpl.EMPTY_EXPRESSION : XExpressionImpl.EMPTY_CODE_FRAGMENT;
155 Language language = text.getLanguage();
156 if (language == null) {
157 if (mySourcePosition != null) {
158 language = LanguageUtil.getFileLanguage(mySourcePosition.getFile());
160 if (language == null) {
161 language = LanguageUtil.getFileTypeLanguage(getEditorsProvider().getFileType());
164 text = new XExpressionImpl(text.getExpression(), language, text.getCustomInfo(), getMode());
166 Collection<Language> languages = getEditorsProvider().getSupportedLanguages(myProject, mySourcePosition);
167 boolean many = languages.size() > 1;
169 if (language != null) {
170 myChooseFactory.setVisible(many);
172 myChooseFactory.setVisible(myChooseFactory.isVisible() || many);
173 //myChooseFactory.setEnabled(many && languages.contains(language));
175 if (language != null && language.getAssociatedFileType() != null) {
176 Icon icon = language.getAssociatedFileType().getIcon();
177 myChooseFactory.setIcon(icon);
178 myChooseFactory.setDisabledIcon(IconLoader.getDisabledIcon(icon));
184 public abstract XExpression getExpression();
187 public abstract JComponent getPreferredFocusedComponent();
189 public void requestFocusInEditor() {
190 JComponent preferredFocusedComponent = getPreferredFocusedComponent();
191 if (preferredFocusedComponent != null) {
192 IdeFocusManager.getInstance(myProject).requestFocus(preferredFocusedComponent, true);
196 public abstract void selectAll();
198 protected void onHistoryChanged() {
201 public List<XExpression> getRecentExpressions() {
202 if (myHistoryId != null) {
203 return XDebuggerHistoryManager.getInstance(myProject).getRecentExpressions(myHistoryId);
205 return Collections.emptyList();
208 public void saveTextInHistory() {
209 saveTextInHistory(getExpression());
212 private void saveTextInHistory(final XExpression text) {
213 if (myHistoryId != null) {
214 boolean update = XDebuggerHistoryManager.getInstance(myProject).addRecentExpression(myHistoryId, text);
215 myHistoryIndex = -1; //meaning not from the history list
222 public XDebuggerEditorsProvider getEditorsProvider() {
223 return myDebuggerEditorsProvider;
226 public Project getProject() {
230 protected Document createDocument(final XExpression text) {
231 return getEditorsProvider().createDocument(getProject(), text, mySourcePosition, myMode);
234 public boolean canGoBackward() {
235 return myHistoryIndex < getRecentExpressions().size()-1;
238 public boolean canGoForward() {
239 return myHistoryIndex > 0;
242 public void goBackward() {
243 final List<XExpression> expressions = getRecentExpressions();
244 if (myHistoryIndex < expressions.size() - 1) {
246 setExpression(expressions.get(myHistoryIndex));
250 public void goForward() {
251 final List<XExpression> expressions = getRecentExpressions();
252 if (myHistoryIndex > 0) {
254 setExpression(expressions.get(myHistoryIndex));