Статьи

Реализация копирования / вставки в Apache Pivot с использованием только скрипта и разметки

В рамках наших усилий по расширению документации для Apache Pivot я недавно работал над некоторыми новыми учебниками, один из которых посвящен поддержке взаимодействия Pivot с системным буфером обмена. В этой статье я расскажу о реализации этого примера приложения, которое, в отличие от большинства предыдущих примеров учебных пособий, которые я написал, полностью построено на разметке и сценариях — Java не используется.

демонстрация

Снимок экрана приложения показан ниже (нажмите для демонстрации в реальном времени). Пользователи могут скопировать одно из трех образцов изображений, предоставляемых приложением, в буфер обмена с помощью кнопки «Копировать», а также могут вставить изображения из буфера обмена с помощью кнопки «Вставить»:

Обратите внимание, что апплет подписан, чтобы позволить ему получить доступ к системному буферу обмена; ненадежные приложения Pivot могут выполнять копирование и вставку только с локальным буфером обмена, содержимое которого не передается другим приложениям.

Реализация

Исходный код приложения состоит из двух файлов: основного файла WTKX, который объявляет структуру пользовательского интерфейса вместе с некоторыми простыми обработчиками событий, и файла JavaScript, который определяет две функции: copy () и paste (). Эти функции вызываются слушателями нажатия кнопок, прикрепленными к элементам пользовательского интерфейса, объявленным в файле WTKX.

WTKX Source

Исходный код WTKX для примера («clipboard.wtkx») показан ниже:

<Window title="Clipboard" maximized="true"
xmlns:wtkx="http://pivot.apache.org/wtkx"
xmlns="org.apache.pivot.wtk">
<wtkx:script src="clipboard.js"/>

<windowStateListeners>
<wtkx:script>
<![CDATA[
function windowOpened(window) {
sourceImageButtonGroup.setSelection(sourceImageButton1);
sourceImageButton1.requestFocus();
}
]]>
</wtkx:script>
</windowStateListeners>

<content>
<TablePane styles="{horizontalSpacing:4, verticalSpacing:4}">
<columns>
<TablePane.Column width="1*"/>
<TablePane.Column width="1*"/>
</columns>
<rows>
<TablePane.Row height="1*">
<Border>
<content>
<CardPane wtkx:id="sourceImageCardPane" styles="{padding:4}">
<ImageView image="org/apache/pivot/tutorials/IMG_0725_2.jpg"/>
<ImageView image="org/apache/pivot/tutorials/IMG_0735_2.jpg"/>
<ImageView image="org/apache/pivot/tutorials/IMG_0767_2.jpg"/>
</CardPane>
</content>
</Border>
<Border>
<content>
<CardPane selectedIndex="0" styles="{padding:4}">
<ImageView wtkx:id="destinationImageView"/>
</CardPane>
</content>
</Border>
</TablePane.Row>

<TablePane.Row height="-1">
<BoxPane orientation="vertical" styles="{fill:true}">
<BoxPane wtkx:id="sourceImageButtonBoxPane"
styles="{horizontalAlignment:'center', verticalAlignment:'center'}">
<wtkx:define>
<ButtonGroup wtkx:id="sourceImageButtonGroup">
<buttonGroupListeners>
<wtkx:script>
<![CDATA[
function selectionChanged(buttonGroup, previousSelection) {
var selection = buttonGroup.getSelection();

if (selection != null) {
var index = sourceImageButtonBoxPane.indexOf(selection);
sourceImageCardPane.setSelectedIndex(index);
}
}
]]>
</wtkx:script>
</buttonGroupListeners>
</ButtonGroup>
</wtkx:define>

<PushButton wtkx:id="sourceImageButton1"
buttonData="IMG_0725_2.jpg" toggleButton="true"
buttonGroup="$sourceImageButtonGroup"/>
<PushButton wtkx:id="sourceImageButton2"
buttonData="IMG_0735_2.jpg" toggleButton="true"
buttonGroup="$sourceImageButtonGroup"/>
<PushButton wtkx:id="sourceImageButton3"
buttonData="IMG_0767_2.jpg" toggleButton="true"
buttonGroup="$sourceImageButtonGroup"/>
</BoxPane>

<BoxPane styles="{horizontalAlignment:'center'}">
<PushButton wtkx:id="copyButton" buttonData="Copy"
ButtonPressListener.buttonPressed="copy()"/>
</BoxPane>
</BoxPane>

<BoxPane styles="{horizontalAlignment:'center', verticalAlignment:'center'}">
<PushButton wtkx:id="pasteButton" buttonData="Paste"
ButtonPressListener.buttonPressed="paste()"/>
</BoxPane>
</TablePane.Row>
</rows>
</TablePane>
</content>
</Window>

Как и в большинстве примеров учебных пособий по Pivot, он определяет один максимизированный недекорированный экземпляр Window верхнего уровня, который содержит остальную часть пользовательского интерфейса. Исходные изображения содержатся в наборе компонентов ImageView, хранящихся в CardPane, а для переключения между ними используется набор кнопок в стиле переключения. Другой ImageView используется для отображения содержимого изображения, вставленного из буфера обмена.

Файл определяет несколько обработчиков событий:

  • Слушатель состояния окна, который инициализирует выбор области карты при открытии окна:

    <windowStateListeners>
    <wtkx:script>
    <![CDATA[
    function windowOpened(window) {
    sourceImageButtonGroup.setSelection(sourceImageButton1);
    sourceImageButton1.requestFocus();
    }
    ]]>
    </wtkx:script>
    </windowStateListeners>
  • Слушатель группы кнопок, который изменяет выбор панели карты в ответ на изменение выбора группы кнопок:

    <buttonGroupListeners>
    <wtkx:script>
    <![CDATA[
    function selectionChanged(buttonGroup, previousSelection) {
    var selection = buttonGroup.getSelection();

    if (selection != null) {
    var index = sourceImageButtonBoxPane.indexOf(selection);
    sourceImageCardPane.setSelectedIndex(index);
    }
    }
    ]]>
    </wtkx:script>
    </buttonGroupListeners>
  • Слушатель нажатия кнопки, который вызывает функцию copy () при нажатии кнопки «Копировать»:

    <PushButton wtkx:id="copyButton" buttonData="Copy"
    ButtonPressListener.buttonPressed="copy()"/>
  • Слушатель нажатия кнопки, который вызывает функцию paste () при нажатии кнопки «Вставить»:

    <PushButton wtkx:id="pasteButton" buttonData="Paste"
    ButtonPressListener.buttonPressed="paste()"/>

П р и м е ч а н и е — Обработчики событий на основе атрибутов, используемые в этом примере, являются функцией Pivot 1.4, которая все еще находится в активной разработке. Однако их можно легко заменить синтаксисом на основе элементов, поддерживаемым в настоящее время доступным Pivot 1.3.

JavaScript Source

Содержимое «clipboard.js» показано ниже:

importPackage(org.apache.pivot.wtk);

function copy() {
// Copy the selected image to the clipboard
var selectedSourceIndex = sourceImageCardPane.getSelectedIndex();
var sourceImageView = sourceImageCardPane.get(selectedSourceIndex);
var sourceImage = sourceImageView.getImage();

var content = new LocalManifest();
content.putImage(sourceImage);

Clipboard.setContent(content);
}

function paste() {
// Paste any available image from the clipboard
var content = Clipboard.getContent();

if (content != null) {
var image = content.getImage();

if (image != null) {
destinationImageView.setImage(image);
}
}
}

Эти две функции выполняют фактическое копирование и вставку данных изображения. Функция copy () получает ссылку на фактическое изображение, отображаемое выбранной картой (экземпляр org.apache.pivot.wtk.media.Image), и устанавливает его как свойство «image» экземпляра LocalManifest. LocalManifest является конкретной реализацией абстрактного класса Manifest, который используется для представления исходных данных в транзакции буфера обмена. Напротив, RemoteManifest представляет данные, полученные из буфера обмена. Локальные манифесты создаются приложением, а удаленные манифесты — системой.

Манифест содержит содержимое, которое может быть помещено в буфер обмена приложением Pivot. Он может представлять данные в различных «разновидностях»: в виде текста, изображения, списка файлов, URL-адреса или пользовательского формата данных. Приложение может предоставлять один или несколько вариантов в зависимости от характера данных. Приложение, которое заинтересовано в использовании данных, может затем выбрать наиболее подходящий формат на основе доступных вариантов.

Как только манифест создан и заполнен, он помещается в буфер обмена с помощью метода Clipboard.setContent (). Теперь он доступен для использования другими приложениями.

Метод paste () выполняет противоположную транзакцию. Он извлекает текущее содержимое буфера обмена и проверяет наличие аромата изображения. Если доступно, он извлекает содержимое изображения и устанавливает его в качестве источника компонента destinationImageView.

Резюме

Хотя это (как и многие учебные приложения) представляет собой несколько надуманный пример, оно демонстрирует, что нетривиальное поведение, такое как взаимодействие с системным буфером обмена, реально может быть реализовано исключительно в разметке и сценарии. Хотя полноценное приложение все еще, скорее всего, будет использовать комбинацию WTKX, Java и JavaScript, этот пример показывает, что можно достичь довольно сложной функциональности всего за несколько строк сценария и разметки.

Для получения дополнительной информации посетите домашнюю страницу Apache Pivot .