Статьи

Переписать приложение рисования платформы NetBeans в среде IDE NetBeans 6.9

Тим Будро переписал части приложения для рисования платформы NetBeans (которое представляет собой образец платформы NetBeans, распространяемый с IDE NetBeans). Измененное приложение Paint (вместе с обновленным учебным пособием) станет частью выпуска IDE NetBeans 6.9.

Существенно изменились две части, обе из которых касаются функции «Сохранить» приложения Paint, и все они находятся внутри PaintTopComponent, как указано ниже.

  1. Интеграция с функциональностью сохранения платформы NetBeans. Вместо того чтобы создавать собственное действие для сохранения холста, теперь вы интегрируетесь со стандартной функцией сохранения платформы NetBeans. Это можно сделать, зарегистрировав контекстно-зависимое действие, которое отслеживает текущий выбор экземпляров интерфейса «org.openide.cookies.SaveCookie». Когда экземпляр этого интерфейса найден в текущем выборе, соответствующий элемент меню и кнопка панели инструментов станут активными. Как это достигается с помощью следующих регистраций в файле слоя:

    <folder name="Actions">
        <folder name="File">
            <file name="org-openide-actions-SaveAction.instance">
                <attr name="instanceCreate" methodvalue="org.openide.awt.Actions.context"/>
                <attr name="delegate" newvalue="org.openide.actions.SaveAction"/>
                <attr name="selectionType" stringvalue="EXACTLY_ONE"/>
                <attr name="surviveFocusChange" boolvalue="false"/>
                <attr name="displayName" bundlevalue="org/openide/actions/Bundle#Save"/>
                <attr name="noIconInMenu" boolvalue="false"/>
                <attr name="iconBase" stringvalue="org/openide/resources/actions/save.png"/>
                <attr name="type" stringvalue="org.openide.cookies.SaveCookie"/>
            </file>
        </folder>
    </folder>
    <folder name="Menu">
        <folder name="File">
            <file name="SaveAction.shadow">
                <attr name="originalFile" stringvalue="Actions/File/org-openide-actions-SaveAction.instance"/>
                <attr name="position" intvalue="100"/>
            </file>
    </folder>
    </folder>
    <folder name="Toolbars">
        <folder name="File">
            <file name="SaveAction.shadow">
                <attr name="originalFile" stringvalue="Actions/File/org-openide-actions-SaveAction.instance"/>
                <attr name="position" intvalue="100"/>
            </file>
        </folder>
    </folder>

    Теперь, когда у нас есть действие, прослушивающее экземпляры интерфейса «SaveCookie», нам нужно ввести эти экземпляры в соответствующее время в текущий выбор. В приложении Paint это делается путем добавления реализации «SaveCookie» к динамическому объекту « InstanceContent » (который мы добавляем в поиск TopComponent в конструкторе TopComponent) всякий раз, когда изменяется холст:

    private void enableSaveAction(boolean canSave) {
    if (canSave) {
    //If the canvas is modified,
    //we add SaveCookie impl to Lookup:
    content.add(saver);
    } else {
    //Otherwise, we remove the SaveCookie impl from the lookup:
    content.remove(saver);
    canvas.addMouseListener(new MouseAdapter() {
    @Override
    public void mouseReleased(MouseEvent e) {
    //Once we can save, we are done listening.
    //If enableSaveAction(false) is called, we will
    //start listening again.
    canvas.removeMouseListener(this);
    enableSaveAction(true);
    }
    });
    }
    }

    Выше saver представляет собой реализацию интерфейса «SaveCookie», который мы рассмотрим во второй части этой статьи. Обратите внимание, что он удаляется из «InstanceContent» всякий раз, когда мы указываем, что холст не может быть сохранен (т. Е. Когда «canSave» имеет значение false). В этот момент мы добавляем «MouseListener» на холст, чтобы мы могли добавить реализацию «SaveCookie» к «InstanceContent» в следующий раз, когда мышь отпущена (то есть, когда мы предполагаем, что изменение было сделано на холсте ).

    Итак, теперь вопрос: «Когда мы вызываем вышеуказанный метод?» Во-первых, в конструкторе TopComponent, так что действие Сохранить отключено по умолчанию, т. Е. При создании окна:

    enableSaveAction(false);

    Во-вторых, в «mouseReleased», как показано выше, чтобы действие сохранения могло быть вызвано при отпускании мыши:

    enableSaveAction(true);

    В-третьих, в реализации «SaveCookie», как показано в следующем разделе этой статьи, каждый раз, когда выполняется сохранение, чтобы отключить включенное действие, чтобы пункт меню и кнопка панели инструментов снова были выделены серым цветом:

    enableSaveAction(false);

    В-четвертых, мы реализуем «ActionListener» в «PaintTopComponent». Затем, когда мы обнаруживаем, что «JButton» является источником вызванного действия, мы знаем, что была нажата кнопка «Очистить», и снова передаем «false» «enableSaveAction».

  2. Реализация интерфейса SaveCookie. Выше мы описали, как интегрировать функции сохранения в платформе NetBeans, используя ее интерфейс «SaveCookie». В верхней части класса мы определяем «saver», то есть то, что добавляется к «InstanceContent» в точках, описанных выше:
    private Saver saver = new Saver();

    Затем, вот определение «Saver», т. Е. Реализация интерфейса «SaveCookie», где мы снова используем «InstanceContent», чтобы различать ситуации, когда файл уже существует, а где нет:

    private class Saver implements SaveCookie {

    @Override
    public void save() throws IOException {
    DataObject theFile = getLookup().lookup(DataObject.class);
    if (theFile != null) {
    File saveTo = FileUtil.toFile(theFile.getPrimaryFile());
    save(saveTo);
    } else {
    saveAs();
    }
    }

    public void saveAs() throws IOException {
    String title = NbBundle.getMessage(Saver.class, "TTL_SAVE_DIALOG");
    File f = new FileChooserBuilder(Saver.class).setTitle(title).showSaveDialog();
    if (f != null) {
    if (!f.getAbsolutePath().endsWith(".png")) {
    f = new File(f.getAbsolutePath() + ".png");
    }
    try {
    if (!f.exists()) {
    if (!f.createNewFile()) {
    String failMsg = NbBundle.getMessage(
    PaintTopComponent.class,
    "MSG_SaveFailed", f.getName());
    DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message(failMsg));
    return;
    }
    } else {
    String overwriteMessage = NbBundle.getMessage(Saver.class, "MSG_Overwrite", f.getName());
    Object userChose = DialogDisplayer.getDefault().notify(new NotifyDescriptor.Confirmation(overwriteMessage));
    if (NotifyDescriptor.CANCEL_OPTION.equals(userChose)) {
    return;
    }
    }
    //Need getAbsoluteFile(), or X.png and x.png are different on windows
    save(f.getAbsoluteFile());
    } catch (IOException ioe) {
    Exceptions.printStackTrace(ioe);
    }
    }
    }

    private void save(File f) throws IOException {
    ImageIO.write(canvas.getImage(), "png", f);
    String savedMessage = NbBundle.getMessage(Saver.class, "MSG_Saved", f.getName());
    StatusDisplayer.getDefault().setStatusText(savedMessage);
    FileObject fob = FileUtil.toFileObject(FileUtil.normalizeFile(f));
    assert fob != null;
    //Store the file, so we don't show the Save dialog again
    content.add(DataObject.find(fob));
    setDisplayName(fob.getName());
    enableSaveAction(false);
    }

    }

Вот и все. Обзор улучшений этого образца, которые будут реализованы в IDE NetBeans 6.9. Обратите внимание, что весь приведенный выше код уже работает с платформой NetBeans 6.8.