package com.intellij.debugger.ui;

import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.debugger.engine.evaluation.CodeFragmentFactory;
import com.intellij.debugger.engine.evaluation.CodeFragmentKind;
import com.intellij.debugger.engine.evaluation.TextWithImports;
import com.intellij.debugger.engine.evaluation.TextWithImportsImpl;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.ui.EditorTextField;
import org.jetbrains.annotations.NonNls;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

/**
 * Created by IntelliJ IDEA.
 * User: lex
 * Date: Apr 12, 2004
 * Time: 2:39:17 PM
 * To change this template use File | Settings | File Templates.
 */
public class DebuggerStatementEditor extends DebuggerEditorImpl {
  private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.DebuggerStatementEditor");

  private final EditorTextField myEditor;

  private int    myRecentIdx;

  public DebuggerStatementEditor(Project project, PsiElement context, @NonNls String recentsId, final CodeFragmentFactory factory) {
    super(project, context, recentsId, factory);
    myRecentIdx = getRecentItemsCount();
    myEditor = new EditorTextField("", project, factory.getFileType()) {
      protected EditorEx createEditor() {
        EditorEx editor = super.createEditor();
        editor.setOneLineMode(false);
        editor.setVerticalScrollbarVisible(true);
        return editor;
      }
    };
    setLayout(new BorderLayout());
    add(myEditor, BorderLayout.CENTER);

    DefaultActionGroup actionGroup = new DefaultActionGroup(null, false);
    actionGroup.add(new ItemAction(IdeActions.ACTION_PREVIOUS_OCCURENCE, this){
      public void actionPerformed(AnActionEvent e) {
        LOG.assertTrue(myRecentIdx >= 0);
        // since recents are stored in a stack, previous item is at currentIndex + 1
        myRecentIdx += 1;
        updateTextFromRecents();
      }

      public void update(AnActionEvent e) {
        e.getPresentation().setEnabled(myRecentIdx < getRecentItemsCount());
      }
    });
    actionGroup.add(new ItemAction(IdeActions.ACTION_NEXT_OCCURENCE, this){
      public void actionPerformed(AnActionEvent e) {
        if(LOG.isDebugEnabled()) {
          LOG.assertTrue(myRecentIdx < getRecentItemsCount());
        }
        // since recents are stored in a stack, next item is at currentIndex - 1
        myRecentIdx -= 1;
        updateTextFromRecents();
      }

      public void update(AnActionEvent e) {
        e.getPresentation().setEnabled(myRecentIdx > 0);
      }
    });

    add(ActionManager.getInstance().createActionToolbar(ActionPlaces.COMBO_PAGER, actionGroup, false).getComponent(),
        BorderLayout.EAST);

    setText(new TextWithImportsImpl(CodeFragmentKind.CODE_BLOCK, ""));
  }

  private void updateTextFromRecents() {
    List<TextWithImports> recents = getRecents();
    LOG.assertTrue(myRecentIdx <= recents.size());
    setText(myRecentIdx < recents.size() ? recents.get(myRecentIdx) : new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, ""));
  }

  private List<TextWithImports> getRecents() {
    final LinkedList<TextWithImports> recents = DebuggerRecents.getInstance(getProject()).getRecents(getRecentsId());
    final ArrayList<TextWithImports> reversed = new ArrayList<TextWithImports>(recents.size());
    for (final ListIterator<TextWithImports> it = recents.listIterator(recents.size()); it.hasPrevious();) {
      reversed.add(it.previous());
    }
    return reversed;
  }

  private int getRecentItemsCount() {
    return DebuggerRecents.getInstance(getProject()).getRecents(getRecentsId()).size();
  }

  public JComponent getPreferredFocusedComponent() {
    return myEditor.getEditor().getContentComponent();
  }

  public TextWithImports getText() {
    return createItem(myEditor.getDocument(), getProject());
  }

  public void setText(TextWithImports text) {
    myEditor.setDocument(createDocument(text));
    final Editor editor = myEditor.getEditor();
    if (editor != null) {
      DaemonCodeAnalyzer.getInstance(getProject()).updateVisibleHighlighters(editor);
    }
  }

  public TextWithImports createText(String text, String importsString) {
    return new TextWithImportsImpl(CodeFragmentKind.CODE_BLOCK, text, importsString);
  }

  private static abstract class ItemAction extends AnAction {
    public ItemAction(String sourceActionName, JComponent component) {
      copyFrom(ActionManager.getInstance().getAction(sourceActionName));
      registerCustomShortcutSet(getShortcutSet(), component);
    }
  }

}

@@ -4016,35 +4016,85 @@
     
-return myEditor.getEditor()
+final Editor editor = myEditor.getEditor();%0A    return editor != null? editor
 .get
@@ -4107,24 +4107,35 @@
 tComponent()
+ : myEditor
 ;%0A  %7D%0A%0A  pub

fix NPE