Blog: bugstack.cn

Precipitation, share, grow, let yourself and others can gain something! πŸ˜„

One, foreword

There's no way. If you don't write something exciting, you always look bad!

Before, I didn’t understand. The technology written is the technical content, and the scene written is the scene analysis. But from the reading of readers, I find that people prefer the combination of technology and scene, especially the combination of technology with those shy scenes, although they do not say it.

The main purpose of this section is to show you how to use the toolbar and Tab page to fill the form at the bottom of IDEA, just like the console in IDEA. But this seems to be enough for people to read, because people only from the technical point of view, it is hard to see what the application of this, even if you read it seems to have no idea what the technology can do.

So, what do you do? Make it exciting. We don’t like to lose money in stocks, then the stock market and K line display combined with IDEA plug-in development. Can let the plug-in learning partner, can write code when tired can also look at the stock, perhaps in the critical time can remind you to throw out quickly!

Second, demand and purpose

For the sake of safety, it is necessary to develop a stock plug-in in a relatively private corner of IDEA, so that students who trade stocks can not forget their own concerns about stock buying and selling when coding CRUD.

So to solve this problem, we need several technical points, including: stock data interface, query object encapsulation, IDEA bottom form and toolbar development, scheduled task scanning, Swing UI, stock code configuration and save, form button event listening, etc.

Let’s combine these technical points to solve a real-world scenario problem and see how to develop a stock plug-in in IDEA.

Case development

1. Engineering structure

Guide - idea - the plugin - TAB β”œ ─ ─ the gradle β”” ─ ─ the SRC β”œ ─ ─ the main β”‚ β”” ─ ─ Java β”‚ β”” ─ ─ cn. Bugstack. Guide. Idea. The plugin β”‚ β”œ ─ ─ domain β”‚ β”‚ β”œ ─ ─ Model β”‚ β”‚ β”‚ β”œ ─ ─ aggregates β”‚ β”‚ β”‚ β”‚ β”” ─ ─ StockResult. Java β”‚ β”‚ β”‚ β”” ─ ─ vo β”‚ β”‚ β”‚ β”œ ─ ─ Data. The Java β”‚ β”‚ β”‚ β”œ ─ ─ GoPicture. Java β”‚ β”‚ β”‚ β”” ─ ─ Stock. Java β”‚ β”‚ β”” ─ ─ service β”‚ β”‚ β”œ ─ ─ impl β”‚ β”‚ β”‚ β”” ─ ─ StockImpl. Java β”‚ β”‚ β”” ─ ─ IStock β”‚ β”œ ─ ─ factory β”‚ β”‚ β”” ─ ─ β”œβ”€β”€ Java β”‚ β”œβ”€ Java β”‚ β”œβ”€ Java β”‚ β”œβ”€ Java β”‚ β”œβ”€ Java β”‚ β”œβ”€ Java β”‚ β”œβ”€ Java β”‚ β”œβ”€ Java β”‚ β”œβ”€moduleβ”‚ β”‚ β”œ ─ ─ RefreshBar. Java β”‚ β”‚ β”œ ─ ─ SettingBar. Java β”‚ β”‚ β”” ─ ─ ViewBars. Java β”‚ β”” ─ ─ the UI β”‚ β”‚ β”œ ─ ─ ConsoleUI. Java β”‚ β”‚ β”œ ─ ─ Consoleui. form β”‚ β”œβ”€ β”œβ”€ resources β”‚ β”œβ”€ meta-inf β”‚ β”œβ”€ download.xml β”œ ─ ─ build. Gradle β”” ─ ─ gradle. PropertiesCopy the code

Bugstack wormhole stack can be downloaded from the whole IDEA plug-in source code

This IDEA plug-in project is mainly divided into five areas:

  • Domain: the domain layer, which provides data services for querying the stock interface. If you are doing some other tool-based functions, you can also put the content of the business class into the domain.
  • Factory: Factory layer, which mainly provides an entry object generated by the tool form to create our own added form content.
  • Infrastructure: A base layer that provides a data store object, which is an operation that can be created and configured in plugin.xml.In this way, after we have configured the stock code, the power off and restart IDEA can also read the configuration
  • Module: a module that provides some tool page operations for use with UI forms. ViewBars, for example, are instantiated in TabFactory to display the forms you add.
  • UI: In this part, the forms generated by automatic drag and drop in IDEA are used to avoid the complexity of handwriting. Some simple pages can be dragged and dragged directly.This is also a low code oh!

Next, we’ll take a look at the implementation process for each of the core function points, which you can download in advance to make it easier to understand.

  1. Implement ToolWindowFactory to develop a form at the bottom to host the desired content
  2. Left is the side toolbar, configuration of self-selected stocks, refresh the stock index
  3. On the right are two TAB pages, which are used to display stock data and K-chart respectively. The data here needs to be provided through the stock interface

2. Click TAB

First here we first use the IDEA plug-in development, Swing UI function, drag and drop two simple forms. So if you have a basic structure like this you should have a picture in your head.

2.1 Optional stock configuration form

public class GidConfig implements Configurable {

    private JPanel mainPanel;
    private JPanel settingPanel;
    private JLabel gidLabel;
    private JTextField gidTextField;

    private ConsoleUI consoleUI;

    public GidConfig(ConsoleUI consoleUI){
        this.consoleUI = consoleUI;
    }

    public JTextField getGidTextField(a) {
        return gidTextField;
    }

    @Override
    public void apply(a) throws ConfigurationException {
        List<String> gidList = DataSetting.getInstance().getGids();
        gidList.clear();
        String[] gids = gidTextField.getText().trim().split(",");
        for (String gid : gids) {
            gidList.add(gid.trim());
        }
        // Refresh dataconsoleUI.addRows(gidList); }}Copy the code
  • In the Java class corresponding to GidConfig, you can obtain the properties displayed on some Windows. When the user clicks the confirm button on the form, we can get the stock symbol configured by the user in Apply and read and set the stock data.

2.2 Stock display form

public class ConsoleUI {

    private JTabbedPane tabbedPane1;
    private JPanel one;
    private JPanel two;
    private JLabel picMin;
    private JTable table;
    private JLabel picDay;

    // Query the data service
    private IStock stock = new StockImpl();

    private DefaultTableModel defaultTableModel = new DefaultTableModel(new Object[][]{}, new String[]{"Stock"."Code"."New"."Fall"."Gains"});

    public ConsoleUI(a) {
        // Initial data
        table.setModel(defaultTableModel);
        addRows(DataSetting.getInstance().getGids());

        // Add events
        table.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                int row = table.getSelectedRow();
                Object value = table.getValueAt(row, 1);
                GoPicture goPicture = stock.queryGidGoPicture(value.toString());
                try {
                    // min K line
                    picMin.setSize(545.300);
                    picMin.setIcon(new ImageIcon(new URL(goPicture.getMinurl())));

                    // Day K line
                    picDay.setSize(545.300);
                    picDay.setIcon(new ImageIcon(new URL(goPicture.getDayurl())));
                } catch(MalformedURLException m) { m.printStackTrace(); }}}); }public JTabbedPane getPanel(a) {
        return tabbedPane1;
    }

    public void addRows(List<String> gids) {
        / / query
        List<Data> dataList = stock.queryPresetStockData(gids);

        / / to empty
        int rowCount = defaultTableModel.getRowCount();
        for (int i = 0; i < rowCount; i++) {
            defaultTableModel.removeRow(0);
        }

        / / add
        for (Data data : dataList) {
            defaultTableModel.addRow(newString[]{data.getName(), data.getGid(), data.getNowPri(), data.getIncrease(), data.getIncrePer()}); table.setModel(defaultTableModel); }}}Copy the code
  • The ConsoleUI class, which corresponds to the display form, is responsible for rendering, updating, and performing events on each piece of data, and is available when the user clicks on a piece of dataK lineSee the corresponding stock index in the page.

3. Stock box setting

After developing the UI form, we also need to use an inherited implementation class of SimpleToolWindowPanel that holds the toolbar and page Settings.

3.1 Settings – Toolbar

cn.bugstack.guide.idea.plugin.module.SettingBar

public class SettingBar extends DumbAwareAction {

    private ViewBars panel;

    public SettingBar(ViewBars panel) {
        super("Stock allocation"."Click to setting", IconLoader.getIcon("/icons/config.svg"));
        this.panel = panel;
    }

    @Override
    public void actionPerformed(@NotNull AnActionEvent e) {
        ShowSettingsUtil.getInstance().editConfigurable(panel.getProject(), newGidConfig(panel.getConsoleUI())); }}Copy the code
  • The Settings toolbar, located at the far left of the custom plug-in panel, is used to set the optional stock symbol.
  • By means ofactionPerformedThe use ofShowSettingsUtilThe utility class launches the UI form.

3.2 Refresh – Toolbar

cn.bugstack.guide.idea.plugin.module.RefreshBar

public class RefreshBar extends DumbAwareAction {

    private ViewBars panel;

    public RefreshBar(ViewBars panel) {
        super("Refresh index"."Click to refresh", IconLoader.getIcon("/icons/refresh.svg"));
        this.panel = panel;
    }

    @Override
    public void actionPerformed(@NotNull AnActionEvent e) { panel.getConsoleUI().addRows(DataSetting.getInstance().getGids()); }}Copy the code
  • The refresh toolbar is mainly used to manually trigger the refresh of the latest results of the stock. The reason for using manual refresh is that this interface has a limit on the number of queries. If the scheduled task has been running, the limit of 100 queries will be used up for a while.But just to reflect the use of technology in the column, adding multiple Settings makes it easier to know how to add them

3.3 Forms fill panel

cn.bugstack.guide.idea.plugin.module.ViewBars

public class ViewBars extends SimpleToolWindowPanel {

    private Project project;
    private ConsoleUI consoleUI;

    public ViewBars(Project project) {
        super(false.true);
        this.project = project;
        consoleUI = new ConsoleUI();

        // Sets the form sidebar button
        DefaultActionGroup group = new DefaultActionGroup();
        group.add(new SettingBar(this));
        group.add(new RefreshBar(this));

        ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar("bar", group, false);
        toolbar.setTargetComponent(this);
        setToolbar(toolbar.getComponent());

        / / add
        JBSplitter splitter = new JBSplitter(false);
        splitter.setSplitterProportionKey("main.splitter.key");
        splitter.setFirstComponent(consoleUI.getPanel());
        splitter.setProportion(0.3 f);
        setContent(splitter);
    }

    public Project getProject(a) {
        return project;
    }

    public ConsoleUI getConsoleUI(a) {
        returnconsoleUI; }}Copy the code
  • In the fill-in panel, we added a toolbar on the left and a stock display panel in the rest of our custom plug-in.
  • DefaultActionGroupTo add Settings and refresh buttons, and eventually populate toActionToolbarGo inside. That’s all set up.
  • JBSplitterIt’s a dividing line, filling our stock index display panel on the rightsplitter.setFirstComponent(consoleUI.getPanel())

4. Fill the main panel to the IDEA toolbar

4.1 Form Factory

cn.bugstack.guide.idea.plugin.factory.TabFactory

public class TabFactory implements ToolWindowFactory {

    @Override
    public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
        / / form
        ViewBars viewPanel = new ViewBars(project);
        // Get an instance of the content factory
        ContentFactory contentFactory = ContentFactory.SERVICE.getInstance();
        // Get what is displayed in ToolWindow
        Content content = contentFactory.createContent(viewPanel, "Stock".false);
        // Set what ToolWindow displays
        toolWindow.getContentManager().addContent(content, 0);

        // A timed task, automatically refresh the stock
        / * for daily query number, here is not open timing task, the user will be able to apply for https://dashboard.juhe.cn/home Timer Timer = new Timer (); timer.schedule(new TimerTask() { @Override public void run() { viewPanel.getConsoleUI().addRows(DataSetting.getInstance().getGids()); }}, 3000, 2000); * /}}Copy the code
  • There are two main parts in TabFactory, one is to populate the ViewBars into the toolWindow, and the other is the timed task to refresh the stock data that we’ve commented out so far.
  • Here due to the stock interface query times limit, so the timed task annotation, otherwise a short time to run out of available times.

4.2 Configuring Windows

plugin.xml

<idea-plugin>
    
    <extensions defaultExtensionNs="com.intellij">
        <! -- Add your extensions here -->
        <toolWindow id="XUtil"
                    canCloseContents="true"
                    anchor="bottom"
                    factoryClass="cn.bugstack.guide.idea.plugin.factory.TabFactory"
                    icon="/icons/stock.png"
        />

    </extensions>

</idea-plugin>
Copy the code
  • Here we configure the form to the bottom of the entire IDEA interfaceanchor="bottom" This location is convenient and the safest

5. Configure persistent data

  • After you use IDEA to configure some basic parameters, such as Maven, Gradle, Git, signature information, etc., the configuration information will be saved when you shut down or restart IDEA.
  • So the optional stock symbol configuration that we developed for this plug-in should also be saved, otherwise it cannot be reset every time IDEA is started. So here we need to useplugin.xml δΈ­ applicationServiceIt’s configuredPersistentStateComponentData Settings store class.

5.1 Object Data

cn.bugstack.guide.idea.plugin.infrastructure.DataState

public class DataState {

    private List<String> gids = new ArrayList<>();

    public List<String> getGids(a) {
        return gids;
    }

    public void setGids(List<String> gids) {
        this.gids = gids; }}Copy the code
  • This is the data object class where you can set the properties you need to store, like gIDS, the stock symbol collection configured by the user.

5.2 Persistent Data

cn.bugstack.guide.idea.plugin.infrastructure.DataSetting

@State(name = "DataSetting",storages = @Storage("plugin.xml"))
public class DataSetting implements PersistentStateComponent<DataState> {

    private DataState state = new DataState();

    public static DataSetting getInstance(a) {
        return ServiceManager.getService(DataSetting.class);
    }

    @Nullable
    @Override
    public DataState getState(a) {
        return state;
    }

    @Override
    public void loadState(@NotNull DataState state) {
        this.state = state;
    }

     public List<String> getGids(a){
        returnstate.getGids(); }}Copy the code
  • The DataSetting class needs to configure persistent objects using the @state annotation provided with IDEA plug-in development
  • We also need to provide a getInstance method to get the data object instance, so we can get the configured object and set and read the data when we actually use it.

5.3 the plugin. The XML configuration

<extensions defaultExtensionNs="com.intellij">
    <! -- Add your extensions here -->
    <applicationService serviceImplementation="cn.bugstack.guide.idea.plugin.infrastructure.DataSetting"/>
</extensions>
Copy the code
  • After creating the data Settings class, you need to use the applicationService tag to configure your class into extensions in plugin.xml.

6. Stock interface

6.1 Technical Investigation

  • No matter what feature development is, these loose ends need to be ironing out before code development begins, a process also known as technical research to design and review. Just like now we need to carry out stock information query, then we need to find an interface that can provide data query, see how this interface applies for use, and what fields the returned object has, whether it meets our expectations.

  • Here fu ge found an aggregation data interface, but only free 100 times/day call, if you have better can be replaced.

  • Interface: web. Juhe. Cn: 8080 / finance/sto… – You need to apply for the key here

  • Data:

6.2 Service Encapsulation

With the stock query interface, you can then do a query and object conversion on the data.

cn.bugstack.guide.idea.plugin.domain.service.impl.StockImpl

public class StockImpl implements IStock {

    / / to application, share API, replacing key can 【 】 can free call 100 times a day: https://dashboard.juhe.cn/home/
    private final String key = "4bc57728***********f0595";

    @Override
    public List<Data> queryPresetStockData(List<String> gids) {
        List<Data> dataList = new ArrayList<>();
        for (String gid : gids) {
            StockResult stockResult = JSON.parseObject(HttpUtil.get("http://web.juhe.cn:8080/finance/stock/hs?gid=" + gid + "&key=" + key), StockResult.class);
            Stock[] stocks = stockResult.getResult();
            for(Stock stock : stocks) { dataList.add(stock.getData()); }}returndataList; }}Copy the code
  • Here we define data VO objects in the Domain domain layer and provide encapsulation of the stock query service. So the caller can directly use this data, if you are the stock query interface provided by other vendors, can also be encapsulated and replaced, as an interface adaptation layer.

4. Test and verification

  • If you download the project without a Plugin and a green arrow, you can configure it yourself:runIdeAnd then it’s ready to go.

Results – The exciting moment is here, no longer worry about writing code to affect the stock oh

1. Allocate stocks

  • The first thing you need to configure here is the stock symbol you care about. I have configured three of my favorites.

2. Pick your own stock index

  • After good configuration, you can see your own stock index, select a later, in the click K line.
  • When you need to see the latest data, you can click the refresh button on the left.

3. The K line

  • Now this is the corresponding K line, isn’t it still pretty sweet. Currently you add the nearest K line and the daily K line, and you can expand the graph in other dimensions.

Five, the summary

  • In this section we used the IDEA form to add a slightly more complex page structure, with sidebars and Tab pages, and to interact and communicate within these page bodies. In addition to the use of data storage Settings, this is often used in the development of IDEA plug-ins.
  • Like the practice of such technology not only can be used to show the stock data, you can also combine their required extension belong to you the content of the actual need in the scene, such as the development of a data set query plugin, you can query the database, ES, Redis, etc, also can be all of the tools set page, the content will have a more technical value.
  • When you take the initiative to add your own features to the source code, frameworks, components, projects, etc., you really start to learn, otherwise a content read not long will be forgotten.

Six, series recommendation

  • How to develop IDEA plug-in?
  • Automatic analysis of r&d delivery quality is realized based on IDEA plug-in development and bytecode staking technology
  • Investigate bytecode staking technology for system monitoring design and implementation
  • “Hand Off Spring” PDF, complete with 260 pages and 65,000 words, complete and distributed!
  • Recognize your technology stack blind spots