суббота, 21 сентября 2013 г.

Morphic. Введение.

Зачем все это нужно?

Разрабатывать интерфейсы приложений приходится рано или поздно всем программистам. Сделать свою программу с красивыми менюшками, полупрозрачными окошками и тетрисом в окне About - это, как чатик для программиста, - обязательный этап посвящения в касту специалистов =)

Цель данного цикла статей - познакомить начинающего программиста Smalltalk с основами идеологии Morphic, разобраться с созданием различных компонентов и построение своего простого оконного приложения. Интересно? Добро пожаловать под кат


Краткий анализ

Smalltalk - мощный язык для разработки приложений широкого спекта, возможно, недооцененный современными разработчиками из-за влияния мейнстримовых языков на процессы разработки крупных приложений. Но это не мешает языку и самой идее развиваться и по сей день.

Мы не можем представить себе серьезное приложение без красивого графического интерфейса. К системам построения интерфейса каждый язык программирования имеет свой подход, но общая концепция их весьма схожа. По своей сути, создание интерфейса в приложениях на различных языках программирования не изменилось аж со времен зарождения стандартов современного ООП. MFC (С++) использует деревянный подход жесткого "хардкода" всех компонентов каждого окна. Сама по себе системная библиотека представляет собой обертку на системными компонентами интерфейса. И естественно, все это надо писать вручную. Есть проектирование и скелетизация прототипа, но ее в расчет не берем.

Действительно приятный и простой инструмент построения интерфейса был представлен в Visual Basic. Понятное контекстное меню с визуальным просмотром результата неимоверно упрощал весь процесс разработки окон. Использовать эту технологию было приятно.


Но, к сожалению, любая попытка сделать свой компонент с поведением, не похожим на
стандартное поведение контролов оборачивалось невероятной болью и блужданием по дебрям WinAPI.

Идеалогия подобного редактора легла в основу инструмента проектирования интерфейса C# приложений, но это уже совсем другая история.

По аналогичным путям развития пошли и другие языки программирования. Но чем же нас порадует Smalltalk?

Morphic наносит удар

Morphic был разработан Джоном Малуни (John Maloney) и Ренди Смитом (Randy Smith) для языка программирования Self (диалект Smalltalk) аж в далеком 1993 году. Позже, Малуни написал новую версию Morphic для Squeak, но основная идеология до сих пор живет и процветает в Pharo Morphic: прямота (directness) и живучесть (liveness). Прямота заключается в том, что все формы, которые представлены на экране - объекты, доступ к которым и непосредственное влияние на которых можно получить при помощи мыши. Живучесть означает, что все эти объекты всегда могут реагировать на все события "внешнего мира" и на действия пользователя.

Разберем простейший пример.
В окне Workspace среды Pharo введем следующий строки
|redSquare blueSquare|
blueSquare := Morph new color: Color blue.
redSquare := Morph new color: Color red.
blueSquare openInWorld.
redSquare openInWorld.
Выдели весь код и выполним его (Ctrl+D).
В левом верхнем углу среды появится два прямоугольника, наложенных друг от друга.



Зажав левой кнопкой мыши красный прямоугольник, перетащим его в другое место рабочей среды и увидим результат:


Тот факт, что мы смогли перетащить два этих объекта как раз следует из идеологии прямоты.
Идеология живучести же требует более глубокого погружения с Morphic и проэктирование собственного класса... Поехали!

Создаем свой Morphic-класс

Для начала необходимо добавить класс, унаследованный от Morph.
Разберем по шагам, что необходимо сделать.

Шаг 1: Добавим собственный пакет

Откроем системный бразуер Pharo (System Browser). В левом списке пакетов добавим новый пакет (Add Package) из контектсного меню (правый клик мыши).
Назовем его Morphic-Custom. Сейчас системный браузер должен выглядеть так:


Шаг 2: Добавим собственный класс

Выберем кликом мышкой наш свежий пакет и в контекстном меню (правая кнопка мыши) на втором листе (список классов выберем) Add Class. Перед нами появится окно добавления нового класса. В него необходимо ввести следующий код:
Morph subclass: #CustomTestMorph
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Morphic-Custom'
Окно должно выглядеть так:
 Жмем на OK. Едем дальше =)

Шаг 3: Добавим собственную отрисовку для нашего объекта

Теперь пришло время добавить собственную отрисовку нашего объекта. По умолчанию рисуется прямоугольник, а нам было бы интересно добавить немного кастомизации. Нажмем на элемент листа --- all --- в третьем листинге. Внизу, в окне кода, появится следующий текст:


Вместо данного текста (который подсказывает нам, что код метода следует добавлять именно сюда =) ) впишем следующий фрагмент кода:

drawOn: aCanvas
|crossHeight crossWidth horizontalBar verticalBar|
crossHeight  := self height / 3.0 .
crossWidth  := self width / 3.0 .
horizontalBar := self bounds insetBy: 0 @ crossHeight .
verticalBar := self bounds insetBy: crossWidth @ 0.
aCanvas fillRectangle: horizontalBar  color: self color.
aCanvas fillRectangle: verticalBar  color:  self color.
После того, как код будет добавлен, шелкните на произвольный листинг браузера. Появится диаологовое окно о том, что были добавлены некоторые изменения в код. Жмем на подтверждение. Среда может запросить имя пользователя, который сделал изменения - это для работы контроля версий, это не особо важно сейчас. Можно ввести абракадабру.

Если все прошло успешно - метод появится в обозревателе методов браузера (самый правый листинг) и окно будет иметь примерно следующий вид:


Вот мы и почти закончили создание нашего класса. Давайте же попробуем отрисовать его!

Шаг 4: Объект в мире

Для отрисовки объекта необходимо открыть окно Workspace, если оно было закрыто, и добавить следующий код:

|test|
test := CustomTestMorph new color: Color blue.
test openInWorld .

Если выполнить данный фрагмент кода, то в левом верхнем углу экрана появится синий крест:

Отлично! Мы создали первый объект Morphic, который существует в мире... Но для того, чтобы он жил полноценной жизнью, в него необходимо поселить несколько методов, которые будут как-то реагировать на действия пользователя.

Шаг 5: Действие по клику. Дадим зеленый свет

Для того, чтобы созданный объект мог реагировать на клик мышкой, необходимо разрешить перехват событий мыщью. Для этого уже расмотренным выше способом добавим новый метод в класс со следующим кодом:
handlesMouseDown: anEvent
^true
Данная строка кода будет давать зеленый свет перхватчику событий нажатия кнопки мыши.

Шаг 6: Реакция на клик

Пришло время добавить измение внешнего вида по клику на объект! Для этого необходимо новый метод в класс CustomTestMorph, код которого приведен далее:
mouseDown: anEvent
self color: Color red.
self changeColor.
После применения внесенных изменений в метод поробуем нажать на крестик. Появится окно выбора цвета, где цветом по умолчанию будет задан красный. Можно выбрать любой цвет и это отразится на объекте:

Итоги

В данной статье был рассмотрен базовый пример создания своего морфик-объекта. Мы убедились в том, что Morphic представляет собой богатую инфраструктуру для создания различных элементов интерфейса с системой событий.

До новых встреч!

1 комментарий:

  1. Еще бы перевести/разобрать саму архитектуру Morphic, начиная с World, Hand и #doOneCicle. Было бы просто супер!

    ОтветитьУдалить