Пишем плагин для Netbeans. Часть первая

в 14:13, , рубрики: java, netbeans, netbeans platform, pastebin, plugin, разработка, метки: , , ,

Представьте ситуацию: вы программируете в среде разработки и вам необходимо кому-то отправить небольшой кусок кода из редактора. Вы выделяете нужный кусок, копируете его, открываете браузер, заходите на pastebin, вставляете код, копируете ссылку, а затем отправляете её адресату. А как насчет того, чтобы сократить эти действия вдвое?
Для Netbeans есть плагин PB4NB, но он не работает из-за смены API в pastebin. Поэтому мы напишем свой собственный плагин, который сами же настроим по своему вкусу, а заодно и немного разберёмся с платформой Netbeans. Заинтересованы? Добро пожаловать под кат.

Подготовка

Чтобы писать плагины для Netbeans нам в первую очередь нужно активировать модуль разработки. Для этого идём в меню «Tools -> Plugins» и на вкладке «Installed» активируем «Developing Netbeans». Далее, нам нужна будет документация по платформе Netbeans. Она доступна в виде плагина на вкладке «Available Plugins» и называется «Netbeans API Documentation». На этом, пожалуй, всё.

Создание проекта

Создаём новый проект («File->New Project->Netbeans Module->Module») и нажимаем «Next».
В поле «Project Name» вводим требуемое имя, пусть это будет «Pastebin», нажимаем «Next».
Заполняем поле «Code Name Base», допустим так «com.pastebin.pastebinplugin» — это будет одновременно и кодовым именем плагина и путём к ресурсам и классам. Поле «Module Display Name» настраивает видимое название плагина в проектах, мы его заполним как «Send to Pastebin.com», но можете вписать туда что-то своё. Остальные поля не трогаем, нажимаем «Finish».
Создался новый проект, структура которого имеет такой вид.
Структура проекта

Создание действия

Теперь мы переходим непосредственно к созданию самого плагина, а именно к классу его действия. Выбираем «Action» в «New->Other->Module Development» и нажимаем «Next».
Выбор класса действия

Нам предлагают выбрать тип действия: «Включен постоянно» или «Включен при условии». Поскольку мы хотим брать выделенный кусок кода из редактора, то есть наш плагин должен быть активным только при открытом редакторе кода, то выберем второй тип «Conditionally Enabled». В «Cookie Class» ставим «EditorCookie», потому что нам нужен доступ к редактору, а не ко всему проекту в целом. «User Selects One Node» оставляем выбранным, поскольку нам нужно, чтобы плагин был доступен при открытии хотя бы одного узла, поддерживающего EditorCookie. Нажимаем «Next».

На следующем шаге мы будем регистрировать GUI для плагина. То есть его местонахождение в окне Netbeans. Доступно расположение в любом из меню, на панели инструментов, а также в контекстных меню. Для начала выставим категорию. Из предложенного списка нам наиболее подходят «Edit» и «Source», выбираем то, что больше всего нравится, я выбрал первое. Затем нужно подумать, как нам проще всего будет вызывать плагин. Лично мне не хотелось, чтоб иконка маячила на панели перед глазами постоянно, поэтому я добавил пункт в меню «Edit», сразу после пункта «Paste». Если же вам будет удобнее запускать плагин по нажатию иконки на панели, то ставим галочку напротив «Global Toolbar Button» и выбираем удобное место. После того, как настроили всё по вкусу, переходим на следующий шаг.

Имя класса заполняем «PastebinAction». «Display Name» лучше заполнить как можно понятнее, например, «Send to pastebin.com», потому что это отображаемое имя пункта меню. Затем выбираем иконку размером 16x16. Если же на предыдущем шаге выбирали место на панели инструментов, то придётся добавить иконку и с размером 24x24. После этого нажимаем «Finish».

Все те настройки, которые мы проделывали, будут видны в сгенерированном коде:

@ActionID(
    category = "Edit",
id = "com.pastebin.pastebinplugin.PastebinAction")
@ActionRegistration(
    iconBase = "com/pastebin/pastebinplugin/pastebin.png",
displayName = "#CTL_PastebinAction")
@ActionReference(path = "Menu/Edit", position = 1250)
@Messages("CTL_PastebinAction=Send to pastebin.com")

Первый запуск

Хотя мы еще ничего толком не писали, но уже можно запустить плагин на проверку. Нажимаем «Run», и ждём появления нового окна Netbeans. После этого откроем произвольный текстовый файл и увидим подобную картину:
image
По непонятным причинам новое окно Netbeans запустилось с русской локализацией, но это не беда, вскоре мы научим наш плагин русскому языку, а пока закроем окно и начнём наконец-то писать код.

Рутина

Нетрудно догадаться, что выполнение плагина будет начинаться с метода actionPerformed, поэтому писать код мы будем в теле этого метода. Для начала поиграемся с EditorCookie, который IDE нам сама же и предложила. Но перед этим добавим необходимые библиотеки, иначе последующий код просто не скомпилируется.
В свойствах проекта выбираем вкладку «Libraries» и нажимаем «Add».
Добавим «Nodes API», и «Editor».
Теперь давайте напишем такой код:

public void actionPerformed(ActionEvent ev) {
    try {
        JEditorPane pane = context.getOpenedPanes()[0];
        pane.setText("// Hello, editor pane!n"+pane.getText());
        context.openDocument().insertString(0, "// Hello, document!n", null);
    } catch (Exception ex) {
        Exceptions.printStackTrace(ex);
    }
}

Этот код добавляет пару строк в текст открытого исходника при вызове плагина. Делается это двумя различными способами — через JEditorPane и через StyledDocument.
Запустив проект на выполнение, открыв любой файл и вызвав плагин, мы увидим, как добавились две строки:
// Hello, document!
// Hello, editor pane!

Что ж, давайте продолжим написание самого плагина. Нам нужно получить выделенный участок текста, а также формат редактируемого исходника, чтобы мы могли правильно настроить подсветку синтаксиса в pastebin. Мы будем пользоваться первым способом — JEditorPane, так как он располагает всеми необходимыми для нас методами. Получать формат подсветки синтаксиса мы будем на основе MIME-типа редактируемого документа.

public void actionPerformed(ActionEvent ev) {
    JEditorPane currentPane = context.getOpenedPanes()[0];
    final String mimeType = NbEditorUtilities.getMimeType(currentPane);
    final String code = getSelectedText(currentPane);
    System.out.println(mimeType + "n" + code);
}

private String getSelectedText(JEditorPane currentPane) {
    String text = currentPane.getSelectedText();
    if (text == null) return currentPane.getText();
    return text;
}

Запустите проект, выделите какой-нибудь кусок кода, запустите плагин и посмотрите результат в консоли. Затем попробуйте ничего не выделяя запустить плагин — на консоль выведется весь исходник. Последняя функция показалась мне удобной, поскольку иногда приходится отправлять код полностью.

Итак, имея на руках код и его MIME-тип, можем приступать к написанию клиента. Вот здесь можно получить справку по Pastebin API и узнать свой ключ разработчика.
Код: PastebinRequest, PastebinSender.
Добавим поле:
private final PastebinRequest request;
И проинициализируем его в конструкторе:
request = new PastebinRequest();
Затем обновим метод actionPerformed:

JEditorPane currentPane = context.getOpenedPanes()[0];
final String mimeType = NbEditorUtilities.getMimeType(currentPane);
final String code = getSelectedText(currentPane);
if (code != null) {
    RequestProcessor.getDefault().execute(new Runnable() {
        @Override
        public void run() {
            setupRequest(code, mimeType);
            String pastedUrl = PastebinSender.sendRequest(request.getRequestMessage());
            System.out.println(pastedUrl);
        }
    });
}

Метод setupRequest я настроил под свои нужды, но вы можете изменить параметры под себя:

private void setupRequest(String code, String mimeType) {
    request.initRequest();
    request.setSourceCode(code);
    request.setFormat(mimeType);
    request.setExpireDate(PastebinRequest.EXPIRE_DATE.ONE_DAY);
    request.setUnlisted(true);
    request.setName("");
}

Перед запуском, давайте еще более упростим вызов нашего плагина, добавив горячую клавишу для его активации.
Заменим строку:
@ActionReference(path = «Menu/Edit», position = 1250)
на:
@ActionReferences({
@ActionReference(path = «Menu/Edit», position = 1250),
@ActionReference(path = «Shortcuts», name = «OS-P»)
})

«OS-P», в данном случае, обозначает «Alt+Shift+P». Если не возникнет конфликта с уже имеющимися горячими клавишами, то запустив проект, мы увидим:
image

Выделяем текст, нажимаем указанную комбинацию и видим на консоли ссылку на размещенный код. Ура, товарищи, мы сделали это! Осталось только вывести диалоговое окно с этой ссылкой. Приступим.
Создадим новый класс и назовём его «UrlDialog». Исходный код этого класса здесь. В класс PastebinAction добавим метод:

private void showUrlDialog(final String pastedUrl) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            Frame frame = WindowManager.getDefault().getMainWindow();
            UrlDialog dialog = new UrlDialog(frame, pastedUrl);
            dialog.setLocation(frame.getWidth() / 2, frame.getHeight()/2);
            dialog.setVisible(true);
        }
    });
}

В методе actionPerformed заменим строку:
System.out.println(pastedUrl);
на:
showUrlDialog(pastedUrl);
Также придётся добавить еще одну библиотеку, для этого в свойствах проекта снова открываем вкладку «Libraries» и добавляем «Window System API».
И, напоследок, нужно открыть файл локализации Bundle.properties и внести туда пару строк:
UrlDialog.title=Pasted url
UrlDialog.copyButton.text=Copy

Вот теперь можно запускать проект. Выделяем код, активируем плагин и видим окно:
Диалоговое окно
При нажатии на кнопку «Copy», ссылка скопируется в буфер обмена. Можно сделать, чтобы это окно сразу закрывалось после копирования, можно вообще окно не показывать, а сразу копировать в буфер. Проявите свою фантазию и сделайте так, как вам будет удобно.

Локализации

В середине статьи я обещал, что мы научим плагин русскому языку. Это не сложно. Взгляните на последнюю аннотацию перед классом PastebinAction. Там красуется строка:
@Messages(«CTL_PastebinAction=Send to pastebin.com»)
Смело её удаляйте, затем откройте Bundle.properties и добавьте туда строку:
CTL_PastebinAction=Send to pastebin.com
Теперь, в окне обозревателя проектов, правой кнопкой мыши щелкните на файле Bundle.properties и выберите «Add->Locale». Из списка предустановленных локализаций выберите русскую и нажмите OK.
image
Добавится новый файл, который следует открыть и изменить. Первую строку можно не переводить, иначе в окне обозревателя проектов она тоже переведётся и будет плохо смотреться:
OpenIDE-Module-Name=Send to Pastebin.com
UrlDialog.title=Ссылка
UrlDialog.copyButton.text=Скопировать
CTL_PastebinAction=Отправить в pastebin.com

Ну что ж, самое время проверить работу. Запускаем и видим:
image

Создание NBM-модуля

Итак, последнее, что нам остаётся сделать — это подключить плагин к Netbeans. Щелкнем правой кнопкой мыши на заголовке проекта и выберем «Create NBM». Netbeans любезно соберёт продукт нашей деятельности в понятный для него файл, который останется только подключить в «Tools->Plugins->Downloaded», нажав «Add plugins» и выбрав наш nbm-файл.

Итоги

Мы создали свой собственный плагин для Netbeans, настроенный «под себя», а также немного познакомились с платформой Netbeans.
Весь проект можно скачать здесь.

Информации по платформе Netbeans довольно мало, но вот ссылка, где хоть что-то можно узнать.

Автор: aNNiMON

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js