package com.kodokux.github.ui; import com.intellij.lang.Language; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.UndoConfirmationPolicy; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diff.DiffContent; import com.intellij.openapi.diff.DiffManager; import com.intellij.openapi.diff.DiffRequest; import com.intellij.openapi.diff.SimpleContent; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.SimpleToolWindowPanel; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileFactory; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.components.JBScrollPane; import com.intellij.ui.treeStructure.Tree; import com.kodokux.github.EditorManager; import com.kodokux.github.GitHubGistFileTreeNode; import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreePath; import java.awt.*; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; /** * Created with IntelliJ IDEA. * User: johna * Date: 13/05/06 * Time: 23:21 * To change this template use File | Settings | File Templates. */ public class GithubGetGistToolWindowView extends SimpleToolWindowPanel implements Disposable { private static final String DIFF_WINDOW_TITLE = "Show differences from previous class contents"; private static final String[] DIFF_TITLES = {"Previous version", "Current version"}; private final ToolWindowManager toolWindowManager; private final KeymapManager keymapManager; private final Project project; private final String extension; private JSplitPane mySplitPane = new JSplitPane(); private JPanel myLeftComponent = new JPanel(new BorderLayout()); private JPanel myRightComponent = new JPanel(new BorderLayout()); { mySplitPane.setOpaque(false); mySplitPane.setBorder(IdeBorderFactory.createEmptyBorder(1, 0, 2, 0)); mySplitPane.setContinuousLayout(true); myLeftComponent.setOpaque(false); myRightComponent.setOpaque(false); } protected Editor editor; protected DefaultTreeModel model; protected Document document; // used for diff view private String previousCode; private VirtualFile previousFile; private Tree jTree; private void writeToEditor() { final Editor mainEditor = FileEditorManager.getInstance(project).getSelectedTextEditor(); if (mainEditor != null) { CommandProcessor.getInstance().executeCommand(mainEditor.getProject(), new Runnable() { @Override public void run() { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { String sourceCode = ""; if (editor.getSelectionModel().hasSelection()) { sourceCode = editor.getSelectionModel().getSelectedText(); } else { sourceCode = editor.getDocument().getText(); } Document document = mainEditor.getDocument(); int offsetStart = mainEditor.getCaretModel().getOffset(); int sourceCodeLength = sourceCode.length(); SelectionModel selectionModel = mainEditor.getSelectionModel(); try { if (selectionModel != null) { if (selectionModel.hasSelection()) { offsetStart = selectionModel.getSelectionStart(); int offsetEnd = selectionModel.getSelectionEnd(); document.replaceString(offsetStart, offsetEnd, sourceCode); selectionModel.setSelection(offsetStart, offsetStart + sourceCodeLength); mainEditor.getCaretModel().moveToOffset(offsetStart + sourceCodeLength); } else { document.insertString(offsetStart, sourceCode); selectionModel.setSelection(offsetStart, offsetStart + sourceCodeLength); mainEditor.getCaretModel().moveToOffset(offsetStart + sourceCodeLength); } } } catch (Exception e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } mainEditor.getScrollingModel(); } }); } }, "Get Gist", UndoConfirmationPolicy.DEFAULT); } else { System.out.println("main editor"); } } public GithubGetGistToolWindowView(final Project project, KeymapManager keymapManager, final ToolWindowManager toolWindowManager) { this(toolWindowManager, keymapManager, project, "php"); } public GithubGetGistToolWindowView(ToolWindowManager toolWindowManager, KeymapManager keymapManager, Project project, String fileExtension) { super(true, true); this.toolWindowManager = toolWindowManager; this.keymapManager = keymapManager; this.project = project; this.extension = fileExtension; ToolWindow window = toolWindowManager.getToolWindow(toolWindowManager.getActiveToolWindowId()); if (null != window) { window.activate(new Runnable() { @Override public void run() { mySplitPane.setDividerLocation(0.25); } }); } setupUI(); } public Editor getEditor() { return editor; } public DefaultTreeModel getModel() { return model; } private void setupUI() { EditorManager editorManager = EditorManager.getInstance(project, FileTypeManager.getInstance().getFileTypeByExtension(extension), true); editor = editorManager.getEditor(); document = editor.getDocument(); DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Gists"); model = new DefaultTreeModel(rootNode); jTree = new Tree(model); jTree.addTreeSelectionListener(new TreeSelectionListener() { @Override public void valueChanged(TreeSelectionEvent e) { Tree _tree = (Tree) e.getSource(); if (_tree.getLastSelectedPathComponent() instanceof GitHubGistFileTreeNode) { final GitHubGistFileTreeNode fileNode = (GitHubGistFileTreeNode) _tree.getLastSelectedPathComponent(); ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { // final PsiFile cache = GithubGetGistCache.getCache(project, fileNode.getFilename()); // int size = 0; // try { // size = Integer.parseInt(fileNode.getSize()); // } catch (NumberFormatException e1) { // } // if (cache == null || cache.getText().length() != size) { // getGistsRawContent(fileNode); // } else { // getEditor().getDocument().setText(cache.getText()); // } getGistsRawContent(fileNode); } }); } } }); jTree.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { Tree _tree = (Tree) e.getSource(); if (_tree.getLastSelectedPathComponent() instanceof GitHubGistFileTreeNode) { if (e.getKeyChar() == KeyEvent.VK_ENTER) { writeToEditor(); } } } }); JBScrollPane jbScrollPane = new JBScrollPane(jTree); myLeftComponent.add(jbScrollPane); JComponent editorComponent = editor.getComponent(); myRightComponent.add(editorComponent); mySplitPane.setLeftComponent(myLeftComponent); mySplitPane.setRightComponent(myRightComponent); add(mySplitPane); DefaultActionGroup group = new DefaultActionGroup(); final ActionManager actionManager = ActionManager.getInstance(); group.add(new ShowSettingsAction()); final ActionToolbar actionToolBar = actionManager.createActionToolbar("Get Gist", group, true); final JPanel buttonsPanel = new JPanel(new BorderLayout()); buttonsPanel.add(actionToolBar.getComponent(), BorderLayout.CENTER); setToolbar(buttonsPanel); } private void getGistsRawContent(final GitHubGistFileTreeNode fileNode) { if (fileNode != null) { new Task.Backgroundable(project, "Get Gist") { public String fileSource; @Override public void onSuccess() { if (fileSource != null) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { try { byte[] b = fileSource.getBytes("Windows-1251"); fileSource = new String(b, "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } getEditor().getDocument().setText(fileSource); //GithubGetGistCache.setCache(project, fileNode.getFilename(), fileSource); } }); } } @Override public void run(@NotNull ProgressIndicator progressIndicator) { try { URL url = new URL(fileNode.getUrl()); HttpURLConnection urlconn = (HttpURLConnection) url.openConnection(); urlconn.setReadTimeout(10000); urlconn.setConnectTimeout(10000); urlconn.setRequestMethod("GET"); urlconn.setRequestProperty("UserAgent", "Kodokux github intellij plugin"); urlconn.setRequestProperty("Accept", "text/html, text/plain"); urlconn.connect(); BufferedReader in = new BufferedReader(new InputStreamReader(urlconn.getInputStream())); StringBuilder buffer = new StringBuilder(); char[] b = new char[1024]; int line; while (0 <= (line = in.read(b))) { buffer.append(b, 0, line); } in.close(); urlconn.disconnect(); fileSource = buffer.toString(); } catch (IOException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } } }.queue(); } } private AnAction createShowDiffAction() { return new ShowDiffAction(); } public static GithubGetGistToolWindowView getInstance(Project project) { return ServiceManager.getService(project, GithubGetGistToolWindowView.class); } @Override public void dispose() { System.out.println("test"); } public void focusInRoot() { // jTree.setSelectionPath(); jTree.setSelectionPath(new TreePath(((DefaultMutableTreeNode) model.getRoot()).getPath())); } private class ShowSettingsAction extends AnAction { private ShowSettingsAction() { super("Settings", "Show settings for ASM plugin", IconLoader.getIcon("/general/projectSettings.png")); } @Override public boolean displayTextInToolbar() { return true; } @Override public void actionPerformed(final AnActionEvent e) { ShowSettingsUtil.getInstance().showSettingsDialog(project, "GitHub"); } } private class ShowDiffAction extends AnAction { public ShowDiffAction() { super("Show differences", "Shows differences from the previous version of bytecode for this file", IconLoader.getIcon("/actions/diffWithCurrent.png")); } @Override public void update(final AnActionEvent e) { e.getPresentation().setEnabled(!"".equals(previousCode) && (previousFile != null)); } @Override public boolean displayTextInToolbar() { return true; } @Override public void actionPerformed(final AnActionEvent e) { DiffManager.getInstance().getDiffTool().show(new DiffRequest(project) { @Override public DiffContent[] getContents() { // there must be a simpler way to obtain the file type // PsiFile psiFile = PsiFileFactory.getInstance(project).createFileFromText("asm." + extension, ""); PsiFile psiFile = PsiFileFactory.getInstance(project).createFileFromText("void johna();", Language.findLanguageByID("java"), "test"); final DiffContent currentContent = previousFile == null ? new SimpleContent("") : new SimpleContent(document.getText(), psiFile.getFileType()); final DiffContent oldContent = new SimpleContent(previousCode == null ? "" : previousCode, psiFile.getFileType()); return new DiffContent[]{ oldContent, currentContent }; } @Override public String[] getContentTitles() { return DIFF_TITLES; } @Override public String getWindowTitle() { return DIFF_WINDOW_TITLE; } }); } } }