1. 程式人生 > 其它 >IDEA Web渲染外掛開發(一)— 使用JCEF

IDEA Web渲染外掛開發(一)— 使用JCEF

目前網上已經有了很多關於IDEA(IntelliJ平臺)的外掛開發教程了,本人覺得簡書上這位作者秋水畏寒 的關於外掛開發的文章很不錯,在我進行外掛開發的過程中指導了我很多。但是綜合下來看,在IDEA上載入網頁的外掛的教程還不是特別多,官方文件也不是那麼的完整。本系列將會從這個角度出發,探討如何編寫載入Web頁面的外掛。

前言

為什麼會有想到開發處理Web網頁的外掛呢?實際上因為在IDEA中,我們可以開啟markdown檔案,並且IDEA具有markdown實時渲染的能力:

因為之前,本人使用過JCEF進行開發。看到這個渲染,心裡大概猜測,應該用了瀏覽器核心。開啟工作管理員:

果然,熟悉的JCEF。然後進入JetBrains的官網,在外掛開發的文件中找到了:

JCEF - Java Chromium Embedded Framework | IntelliJ Platform Plugin SDK (jetbrains.com)

那麼,接下來我們從零開始,編寫一款屬於自己的外掛,這款外掛能夠載入Web頁面。

環境準備

  • JDK 11
  • Gradle
  • 良好的網路環境

我們先建立一個IntelliJ Platform Plugin,名為:intellij-jcef-plugin

然後進行這個Gradle專案的配置工作,完成整個專案搭建。本專案會在最後提交到github供讀者下載。

程式碼編寫

首先說明我們的目的,就是希望能夠類似於gradle、maven外掛一樣,能夠在IDEA的側邊有一個顯示我們Web頁面的地方:

通過閱讀官方的文件我們可以知道,我們需要編寫的是ToolWindow(Tool Windows | IntelliJ Platform Plugin SDK (jetbrains.com))這樣一個頁面窗體。

基礎ToolWindow開發

在開發之前,我們需要明確一點,儘管這一節的標題寫著"空白ToolWindow開發",似乎在暗示我們,接下來我們會開發一個所謂的ToolWindow的實現類。實際上,ToolWindow是外掛框架本身提供的,我們只需要做的是建立UI元件(例如JPanel),然後呼叫ToolWindow例項通過相關的API幫我們把UI元件設定到ToolWindow內部,具體的步驟如下:

實現ToolWindowFactory

建立一個ToolWindowFactory的實現類,這裡我們取名MyToolWindowFactory,然後重寫createToolWindowContent方法。

public class MyToolWindowFactory implements ToolWindowFactory {
    @Override
    public void createToolWindowContent(
            @NotNull Project project,
            @NotNull ToolWindow toolWindow) {
        // 此處方法將會在點選ToolWindow的時候觸發
        // 獲取ContentManager
        ContentManager contentManager = toolWindow.getContentManager();
        Content labelContent =
                contentManager.getFactory() // 內容管理器獲取工廠類
                        .createContent( // 建立Content(元件類例項、顯示名稱、是否可以鎖定)
                                new JLabel("hello, world"),
                                "MyTab",
                                false
                        );
        // 利用ContentManager新增Content
        contentManager.addContent(labelContent);
    }
}

在重寫的createToolWindowContent方法中,外掛框架會為我們傳入兩個物件:Project以及ToolWindow物件。其中,Project物件是當前專案的內容抽象,而ToolWindow這個物件就是外掛框架本身內部構造的,抽象了我們需求所說的,點選側邊欄時候彈出的頁面。

在該方法實現中,主要有以下步驟:

  1. 使用ContentFactory(ContentManager.getFactory()獲取)的createContentAPI建立Content物件。這個建立時候,需要swing元件物件(JPanel、JLabel等等)。
  2. 使用ContentManager的addContentAPI新增步驟1的Content物件。

註冊外掛

接下來,我們將我們實現的MyToolWindowFactory通過plugin.xml進行註冊,alt+enter,IDEA幫助我們快速完成填寫xml配置到plugin.xml中:

進行上述操作後,IDEA自動為我們在plugin.xml檔案的extensions節點中,添加了toolWindow節點的內容,但是我們還需要填寫必備的屬性id

<!-- plugin.xml檔案 -->
    <extensions defaultextensionns="com.intellij">
        <!-- Add your extensions here -->
        <!-- id是必須的屬性,我們進行新增 -->
        <!-- anchor錨點非必須,但是為了像Gradle外掛一樣預設顯示在右邊,我們設定為right -->
        <toolwindow id="myToolWindowFactory" anchor="right" factoryclass="com.compilemind.demo.ui.MyToolWindowFactory">
    </toolwindow></extensions>

解決除錯環境問題

目前為止,我們實現了ToolWindowFactory以及將我們的實現類註冊到plugin.xml中。現在,我們先什麼內容都不編寫,開始除錯我們的外掛:

不過開始除錯後,會有很多的情況發生,這裡我做了一些遇到的問題的總結。

Gradle亂碼

此時進行Debug除錯,在我的機器上會出現亂碼:

解決方案為,在build.gradle中新增如下的語句:

tasks.withType(JavaCompile) {
    options.encoding = "UTF-8"
}

Gradle報錯不知道這樣的主機(Unknown host)

如果出現了類似於Unknown host 'xxxxx.cloudfront.net'. You may need to adjust the proxy settings in Gradle.這樣的報錯,一般是當前網路的連通問題,導致無法下載cloudfront.net一些jar檔案。此時掛代理是最好的辦法。

rumIde:Download JCEF

如果使用除錯模式,intellij外掛開發的Gradle外掛會下載jcef的執行時,這個過程會比較漫長,目前解決辦法是使用好的網路等待下載:

在本人機器上,第一次除錯的時候主要就是遇到上面的三種情況。

驗證基礎ToolWindow

解決完上述的幾個問題之後,介面彈出了我們的除錯下的社群版的IDEA(ideaIC),並且,檢視Plugins頁籤,會發現我們編寫的外掛已經被這個ideaIC安裝了:

我們使用這個IDEA建立一個簡單的空專案,然後可以看到右側有我們提供的ToolWindow:

可以看到,此時的ToolWindow中的內容顯示為我們上面設定的new JLabel("hello, world"),該ToolWindow上方有我們設定的"My Tab"標題。截至目前的程式碼,包含在這個github上這個提交:

simple ToolWindow Content · w4ngzhen/intellij-jcef-plugin@bf2ca8e (github.com)

Web頁面ToolWindow開發

通過上面一些系列的環境搭建,以及ToolWindow開發練習,我們已經瞭解瞭如何開發一款用於IDEA側邊欄展示內容的外掛。當然,我們一開始的需求是要在ToolWindow中展示網頁,並且也知道了,JetBrains已經將JCEF引入到了IntelliJ外掛平臺。接下來,我們使用JCef以及JBCef相關API建立一個用於展示Web的UI元件,再通過上述的方式,新增到ToolWindow。

建立MyWebToolWindowContent

package com.compilemind.demo.ui;

import com.intellij.ui.jcef.JBCefApp;
import com.intellij.ui.jcef.JBCefBrowser;

import javax.swing.*;
import java.awt.*;

public class MyWebToolWindowContent {

    private final JPanel content;

    /**
     * 建構函式
     */
    public MyWebToolWindowContent() {
        this.content = new JPanel(new BorderLayout());
        // 判斷所處的IDEA環境是否支援JCEF
        if (!JBCefApp.isSupported()) {
            this.content.add(new JLabel("當前環境不支援JCEF", SwingConstants.CENTER));
            return;
        }
        // 建立 JBCefBrowser
        JBCefBrowser jbCefBrowser = new JBCefBrowser();
        // 將 JBCefBrowser 的UI控制元件設定到Panel中
        this.content.add(jbCefBrowser.getComponent(), BorderLayout.CENTER);
        // 載入URL
        jbCefBrowser.loadURL("https://cnblogs.com/w4ngzhen");
    }

    /**
     * 返回建立的JPanel
     * @return JPanel
     */
    public JPanel getContent() {
        return content;
    }
}

修改MyToolWindowFactory

這裡,我們將建立MyWebToolWindowContent例項,然後返回其Panel,按同樣的方式設定到ToolWindow中。

驗證Web渲染ToolWindow

上述程式碼完成開發後,我們再次執行Debug模式,可以看到此時的介面顯示了相關的網頁:

附錄

本次程式碼本人放在了Github上,地址為:w4ngzhen/intellij-jcef-plugin (github.com)

上面基礎ToolWindow開發以及web頁面ToolWindow開發兩節的內容,按如下提交對應:

基礎ToolWindow開發 :simple ToolWindow Content · w4ngzhen/intellij-jcef-plugin@bf2ca8e (github.com)

web頁面ToolWindow開發:web ToolWindow Content · w4ngzhen/intellij-jcef-plugin@45604d3 (github.com)