среда, Октябрь 21, 2009

JBoss archives tool

В своём прошлом посте я скромно, и для многих не заметно, пообещал написать об утилите "JBoss archives tool". Данное обещание хоть и было сделано давно, но всё же не забыто. И вот я, наконец, созрел, чтобы написать об этом инструменте пост. Более того меня на это сподвигло постоянное "давление" со стороны моих коллег по работе, стало очевидно, что лучше один раз написать инструкцию, чем каждому по отдельности пальцем показывать какие кнопки и сколько раз нажимать ;-).

JBoss archives tool позволяет автоматически в фоновом режиме пакетировать java-библиотеки и выкладывать их в определенных директориях. В отличии от других сборщиков программных проектов, таких как Ant и Maven инструмент прост в обращении и имеет гуй (GUI).

Для начала напомню как устанавливается данный плагин в IDE. для этого идём в окошко обновлений: Help >> Software Updates >> [вкладка] Available Software. Здесь нам нужно добавить адрес к JBoss Update Site (кнопка "Add Site...") - здесь я оставлю выбор сайта на усмотрение читателя: http://www.jboss.org/tools/download.html. Также, есть возможность, просто, скачать пакет в качестве архива - это можно сделать тут (для Eclipse 3.4.2): https://www.jboss.org/tools/download/stable.html.

После всех этих не простых приготовлений в Eclipse должна появиться View "Project archives" (быстро найти её можно нажав Ctrl+3 и вписав в текстовое поле: "archives") или с помощью меню Window >> Show View >> Other >> JBoss Tools >> Project archives. Теперь можно приступать к эксплуатации: выбрав во вкладке "Package Explorer" проект, для которого необходимо собрать JAR (во вкладке "Project Explorer", особенно в самых последних версиях Eclipse, это реализовано несколько иначе, веселее, но описывать я это не буду), он появится в "Project archives", от куда из меню по правой кнопке выбираем пункт New archives >> JAR:


В появившемся диалоге нет ни чего сверх сложного, нужно только указать имя будущего файла и относительный путь к папке, в которой он создан. По поводу пути к папке было много слов сказано в моём предыдущем посте "Eclipse Enviroment" в пункте "3. Переменные для размещения собранных библиотек", так что действуйте на Ваше усмотрение. Итак, JAR архив создан, но он пустой как барабан. Его необходимо наполнить исполняемыми файлами. Для этого, вернувшись, после нажатия кнопки финиш, к вкладке "Project archives", жмем правой кнопки на появившейся там JAR файл и ищем в меню New Fileset, в результате чего должен появиться похожий диалог:


Надеюсь, тут тоже нет ни чего не понятного, дам только несколько комментариев. Понятно, что "Destination" - это собственно JAR файл в который добавляются наши бинарники, если в данный диалог перешли по вышеописанному пункту меню, то в этом поле должно стоять верное имя библиотеки. Пункт "Root directory" - это это директория в проекте, от куда брать скомпилированные файлы, обычно это папка "bin". Ну и поля "Includes" и "Excludes", куда прописываются маски для файлов, которые необходимо включить/исключить в архив из папки "bin". Всё.

Для того, чтоб добавить файл MANIFEST.MF, ну или вообще какие-либо другие файлы в архив, нужно во вкладке "Project archives" в меню сказать New Folder и уже для неё (т.е. жмакая уже по этой папке), повторить New Fileset:


Ну вот и всё. Если в меню Eclipse стоит галочка Project >> Build Automatically, то сборка архива будет автоматической, принудительно вызвать её можно надавливая на кнопку в виде бочонка с зелёным треугольничком, что во вкладке "Project archives", или из меню, там же "Build Archive (Full)".

четверг, Октябрь 15, 2009

Refactoring

Рефакторинг в IDE Eclipse вызывается через меню Refactor. Названия пунктов меню соответствуют задачам переработки кода, почти соответствуя стандартным названиям рефакторингов.

В моей экспериментальной задаче создания универсального пользовательского интерфейса для вызова любого API выбранного плагина OSGi, я начинаю с обучения как работать с фреймворком OSGi чтобы загрузить информацию о плагинах (bundle).

Сначала нужно вывести список плагинов конфигурации.


for (Bundle bundle : context.getBundles()) {
System.out.println( bundle.getBundleId() + " "
+ bundle.getSymbolicName() + " "
+ convertState( bundle.getState()));
}

Context типа BundleContext - параметр, передающийся при активации методу start активатора плагина. Весь код также вызывается оттуда. (В новой версии API2UI я сделал интерфейс через OSGi console, но я там пока не делал рефакторинг.)

Введя название метода convertState, жму Ctrl+1, выбираю create method ... и вписываю тело метода.

 
private String convertState( int state ) {
switch ( state ) {
case 1:
return "UNINSTALLED";
case 2:
return "INSTALLED";
case 4:
return "RESOLVED";
case 8:
return "STARTING";
case 16:
return "STOPPING";
case 32:
return "ACTIVE";
default:
return "";
}
}

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


0 org.eclipse.osgi ACTIVE
1 org.eclipse.ui STARTING
...
60 org.eclipse.core.filesystem.win32.x86 RESOLVED

Теперь нужно дать возможность выбора плагина по Id.

Bundle bundle = context.getBundle( id );

Найдя в интернете код ввода long, получаю:


super.start( context );
context.getBundle(); // чтобы избежать Exception'а при вызове теста

// 1. вывод списка плагинов
for ( Bundle bundle : context.getBundles()) {
System.out.println(bundle.getBundleId() + " "
+ bundle.getSymbolicName() + " "
+ convertState(bundle.getState()));
}

// 2. ввод id
BufferedReader bf = new BufferedReader( new InputStreamReader( System.in ));
System.out.println( "Enter Bundle Id:" );
String s = null;
try {
s = bf.readLine();
}
catch ( IOException e ) {
e.printStackTrace();
}

long id = Long.parseLong( s );
Bundle bundle = context.getBundle( id );

// 3. дальнейшая работа с выбранным плагином
System.out.println( bundle.getSymbolicName());
...

Надо причесать. И тут, выделяем 1 и 2 жмем Refactor->Extract Method... вводим название метода selectBundle, OK. И выбор плагина выделяется в отдельный метод:


super.start( context );
context.getBundle();
Bundle bundle = selectBundle( context );

// 3. дальнейшая работа с выбранным плагином
System.out.println( bundle.getSymbolicName());
и

private Bundle selectBundle( BundleContext context ) {
for ( Bundle bundle : context.getBundles()) {
System.out.println(bundle.getBundleId() + " "
+ bundle.getSymbolicName() + " "
+ convertState(bundle.getState()));
}

BufferedReader bf = new BufferedReader( new InputStreamReader( System.in ));
System.out.println( "Enter Bundle Id:" );
String s = null;
try {
s = bf.readLine();
}
catch ( IOException e ) {
e.printStackTrace();
}

long id = Long.parseLong( s );
Bundle bundle = context.getBundle( id );
return bundle;
}

Вторую часть метода selectBundle тоже можно выделить в отдельный метод.


Bundle bundle = inputId( context );

private Bundle inputId( BundleContext context ) {
BufferedReader bf = new BufferedReader( new InputStreamReader( System.in ));
System.out.println( "Enter Bundle Id:" );
String s = null;

try {
s = bf.readLine();
}
catch (IOException e) {
e.printStackTrace();
}

long id = Long.parseLong( s );
Bundle bundle = context.getBundle( id );
return bundle;
}

Последняя часть кода слишком усложнена. Inline... - выделяем "bundle", OK:


return context.getBundle( id );

Теперь можно выделить в отдельный метод ввод:


long id = readInput();

private long readInput() {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter Bundle Id:");
String s = null;

try {
s = bf.readLine();
}
catch ( IOException e ) {
e.printStackTrace();
}

return Long.parseLong( s );
}

А строковый литерал вытянем в параметр. Introduce Parameter... - выделяем литерал, вводим название параметра - msg:


private Bundle selectBundle(BundleContext context) {
for ( Bundle bundle : context.getBundles()) {
System.out.println(bundle.getBundleId() + " "
+ bundle.getSymbolicName() + " "
+ convertState(bundle.getState()));
}

return context.getBundle(readInput("Enter Bundle Id:"));
}

private long readInput(String msg) {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
System.out.println(msg);
String s = null;

try {
s = bf.readLine();
}
catch (IOException e) {
e.printStackTrace();
}

return Long.parseLong( s );
}


Вывод:


0 org.eclipse.osgi ACTIVE
1 org.eclipse.ui STARTING
...
60 org.eclipse.core.filesystem.win32.x86 RESOLVED
Enter Bundle Id:
1
org.eclipse.ui


Также про это написано в книге Martin Fowler, Refactoring: Improving the Design of Existing Code (Рефакторинг. Улучшение существующего кода).

P.S. К тому же, рефакторинг - одна из методик agile (гибких) процессов разработки.

среда, Июнь 24, 2009

Galileo is here!



Релиз Eclipse 3.5 Galileo вышел в свет. Поздравляем всех!

Страница для закачек: http://www.eclipse.org/downloads/

понедельник, Июнь 22, 2009

Eclipse Enviroment

В этой статье я хочу немого рассказать о том, как с помощью различных переменных окружения и строк подстановок можно настроить свою Eclipse IDE для удобства, в первую очередь, тем кто ведёт совместную разработку проектов, а также тем, кто просто любит порядок и системность во всем.

Думаю мне не стоит объяснять для чего и как используются системные переменные окружения, а также, что такое строки подстановки и где они применяются... Пользу от переменных значений в программировании сложно переоценить. Но вопрос - насколько значнения системных переменных окружения переменны? Т.е. я хочу сказать - как часто и на сколько легко править системные переменные окружения? Если вы скажите, что редко и эта процедура вполне удобна, то, думаю, эта статья будет вам не особо интересна. Лично я, довольно давно работаю с несколькими проектами, в которых активно используются кое-какие системные перменные, при этом, значения от этих переменных проекты ожидают разные, понятно: пути к библиотекам и ресурсам для разных проектов - разные, а переменная одна. Приходится как-то переключатся. Это можно делать по разному:


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

  • скрипт запуска приложений с нужными переменными - так например, можно запускать Eclipse IDE или своё приложение с помощью отдельных скриптов, в которых перед вызовом самого приложения предварительно прописать экспорты (export) (или сеты (set) для Windows) тех или иных переменных окружения. Вариант более удобный и в каких-то случаях вполне приемлемый, но мы будем говорить о том как, по крайней мере внутри Eclipse IDE, достигнуть этого же эффекта более элегантным способом.


Предположим, что у нас есть проект, который называется "MyPrj". Пусть у этого проекта есть корневая директория, в которой находится сам файл для запуска приложения, а также его конфигурационные файлы и какие-то библиотеки, такие как log4j.jar и тому подобные. Таким образом, есть примерная структура проекта:

/home/sk/myprj/root [кореневая директория]
|-- bin [папка для рабочих файлов проекта]
|-- config [папка с конфигурацией]
`-- libs [какие-то библиотеки]

Теперь посмотрим, что можно сделать в настройках Eclipse Workspace.

1. Переменные для сборки

Вообще надо сказать, что настройки Eclipse, относящиеся к проектам, заданы по умолчанию на уровне IDE, но они могут быть переопределены в свойствах конкретного проекта, это можно называть по умному - project-specific settings.

Таким образом для начала работы, если мы хотим использовать у себя в проекте библиотеку log4j.jar, то мы должны сказать проекту, где она лежит. А для этого необходимо определить, так называемые classpath variable, в настроеках проекта: Project >> Properties >> Java Build Path. В этом окне можно добавлять пути к внешним библиотекам разными способами, описывать каждый я не буду - мы хотим использовать переменные, поэтому жмем "Add Variable". Далее, чтобы создать свою переменную нужно нажать ещё несколько кнопок: Configure Variables >> New. Назовем переменную MYPRJ_ROOT и в качестве значения укажем корневую директорию проекта:


Далее, создав переменную, её можно использовать для формирования пути к библиотекам - в диалоге "Add Variable", выбираем из списка MYPRJ_ROOT и жмем на кнопку "Extend" и ищем в списке нужную библиотеку:


Описаный способ подключений библиотек, в общем-то вполне очевиден, также понятно в чём плюс такого подхода: при разработке проекта несколькими людьми на разных машинах пути к директории libs могут (и скорее всего будут) отличатся. Используя переменную - проблема будет состоять только в том, чтобы каждый разработчик настроил у себя в workspace нужным образом classpath variable (понятно, что в этом случае название переменной должно быть оговорено и быть стабильным).


2. Внутренние переменные окружения Eclipse IDE

Хорошо, проект у нас есть, необходимые библиотеки подключенны, теперь нам нужно, чтобы во время отладки из под Eclipse проект использовал переменные окружения.

В Eclipse есть возможность запускать проекты каждый со своими индивидуальными настройками, вплоть настроек значений переменных окружения. Для этого в окне настроек Eclipse (Window >> Preferences >> Run/Debug >> String Substitution) создадим строку подстановки, которую в последствии используем в качестве значения для внутренней переменной окружения Eclipse:


Назовем строку подстановки, как и в пункте 1 - "MYPRJ_ROOT" (хотя это и не обязательно, более того не надо путать переменые описанные в пункте 1 и строки подстановки, а также переменные окружения - это разные вещи) и снова укажем в качестве значения корневую директорию проекта: /home/sk/myprj/root.

Теперь нам при запуске приложения необходимо указать JVM правильный CLASSPATH. Для этого в диалоге "Run Configurations", во вкладке "Enviroment" нужно создать внутреннюю переменную окружения для проекта. И опять назовем её "MYPRJ_ROOT"... честно сказать я обычно и в реальном проекте так делаю и даже не путаюсь в итоге, но вообще, опять же - всё зависит от ситуации и личных взглядов.


Далее во вкладке "Arguments", в поле "VM arguments" напишем следующее заклинание (одинаково для любой ОСи):

-Djava.ext.dirs=${MYPRJ_ROOT}/libs

Теперь, во-первых, запускаемое приложение будет полностью уверенно, что в системе есть переменная окружения ${MYPRJ_ROOT} (или %MYPRJ_ROOT% на виндовый манер), которую можно использовать во время выполнения, например, как-нибудь так:


а во-вторых: CLASSPATH обращен к директории /home/sk/myprj/root/libs, где JVM будет искать необходимые библиотеки для проекта, и этот путь с нашей точки зрения будет являтся относительным (как минимум относительно данного проекта).

Здесь оговорюсь: использование переменных окружения в качестве нахождения пути к папке с проектом - не лучший способ, тут я просто продемонстрировал пример использования переменных окружения, может не самый удачный, но смысл тут остаётся один - показать то, как в Eclipse IDE создать окружение для отлаживаемого приложения.


3. Переменные для размещения собраных библиотек

Следующий шаг - это выкладываение собраной библиотеки нашего проекта в директорию, от куда её потом можно будет запускать в качестве stand alone приложения.

Конечно, сборкой проекта, особенно крупного, должны заниматься монстровые инструменты, такие как Ant и Maven, а всякие там гуёвые решения (от англ. GUI) - это, понятно, от лукавого. Но всё же рассмотрим именно последный, т.е. гуёвый, вариант, коли уж мы говоим о переменных подстановки. Сразу скажу, что путь этот несколько тернист и сразу не очевиден...

Есть такая замечательная вещь как JBoss Tools - это набор расширений Eclipse для работы с продуктами JBoss - Hibernate, JBoss AS, JSF, Seam и т.д и т.п... В этом, почти бесконечном, наборе инструментов, есть такая, сразу не заметная, вещь как JBoss archives tools, она позволяет автоматом пакетировать java-библиотеки и выкладывать их в указаных местах. Как с помощью этого инструмента пакетировать проект - это тема для отдельного, пусть и не длинного, разговора, напишу об этом в следующем посте, а вот как выкладывать собраные библиотеки мы поговорим прямо сейчас.

Прежде, чем начать забивать гвозди - нужно взять молоток в руку. Тем кто пользуется целым пакетом JBoss Tools, в каких-то своих целях, проще - у них инструментальный ящик под есть рукой и достать от туда молоток не проблема. А вот, для тех у кого этого счастья нет, и вообще не понятно нафиг оно нужно - есть два варианта: либо вообще плюнуть на это дело, либо скачать молоток отдельно. Устанавливать у себя целиком JBoss Tools ради одного инструмента - сомнительное удовольствие, JBoss archives tools можно легко установить отдельно, не выходя из Eclipse, для этого идём в окошко одновлений: Help >> Software Updates >> [вкладка] Available Software. Здесь нам нужно добавить адрес к JBoss Update Site (кнопка "Add Site...") - здесь я оставлю выбор сайта на усмотрение читателя: http://www.jboss.org/tools/download.html. Также, есть возможность, просто, скачать пакет в качестве архива - это можно сделать тут (для Eclipse 3.4.2): https://www.jboss.org/tools/download/stable.html.

После всех этих не простых приготовлений в Eclipse должна появиться View "Project archives" (быстро найти её можно нажав Ctrl+3 и вписав в текстовое поле: "archives"). Теперь можно приступать к эксплуатации: выбрав наш проект, он появится в "Project archives", от куда по правой кнопке перейдем в диалог создания нового JAR файла. Здесь настраивая содержимое архива нашего проекта можно указать путь назначения для сборки. И сделать это можно, опять же с помощь внутренних переменных окружения Eclipse - указав в поле "Destination": ${MYPRJ_ROOT}/bin/, и выбрав для "Replace to" пункт "file system":


В общем-то это всё. После создания и настройки архива, во View "Project Explorer" (к сожалению, только в этой View) у проекта должна появится такая штука:


т.е. кнопка сборки архива проекта всегда под рукой и копирование архива при этом происходит сразу в нужное место. Очень удобно.

В общем надеюсь, статья окажется полезной. На этом у меня всё.

вторник, Июнь 02, 2009

Eclipse Modeling Framework Overview

Я собираюсь разобраться с Eclipse Modeling Framework и поделиться своими открытиями.
Первое открытие: Eclipse (3.4.2) поддерживает UML 2.1.
Эта модель классов позволяет получить код.

Нужно создать EMF Model (файл .genmodel), импортируя созданную модель.

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

Здесь требуется указать тип-параметр у дженерика EEList. У меня это не получается. (Как позже выяснилось, нужно делать либо ассоциации-референсы, либо максимальную кратность атрибута *, по крайней мере в Ecore.)
Тогда, переделываю UML.
Т. к. нет простого пути указать кратность ассоциации, перехожу в ECore - модель промежуточного (канонического) формата EMF.

Перегенерирую UML (через контекстное меню genmodel'и) чтобы актуализировать изменения из ECore (это не обязательно, UML использовать вообще не обязательно):

Запускаю генерацию кода (Generator > Generate All). Второе открытие: для нашей модели даже генерируется по умолчанию какой-то пользовательский интерфейс. Получается 4 плагина:
  • model - это сама модель с фабриками для создания объектов
  • edit - промежуточный код редактирования объектов модели
  • editor - UI-код редактора модели
  • tests - скелеты тестов

Можно сгенерировать отдельные плугины по соответствующим пунктам меню Generator.
Запускаем плагин editor как часть Workbench'а... Вот он:

Это редактор инстансов объектов нашей модели, который можно даже немного настроить при генерации и, конечно, поправить исходники.
А код модели обладает (автоматически, бесплатно и по умолчанию) функциями оповещения наблюдателей об изменениях, персистенции в ресурсы (опять же настраиваемой опциями) и своим рефлексивным API.
В общем, ищу единомышленников по освоению Eclipse Modeling Framework и связанных с ним проектов.

P. S.
Основная книга Eclipse Modeling Framework: A Developer's Guide.
Еще есть перспективный проект по модели UI для нашей прикладной модели - Eclipse Presentation Modeling Framework (PMF) (пока к сожалению медленно развивающийся). Вот пример работы фреймворка, ложащегося в основу этого проекта.

среда, Май 27, 2009

Eclipse 3.5 Galileo

Всем привет.

Для начала хочу объяснить причину своего продолжительного отсутствия: 2 февраля 2009 года у меня родился сын (если кому интересно, чуть более подробно об этом я писал здесь: http://sergej-k.livejournal.com/14710.html)! Это событие сильно изменило мой, до этого момента, привычный образ жизни. Конечно, изменения произошли исключительно в лучшую сторону, но это сказалось на моём сетевом и не только времяпрепровождении.

В общем, этот блог, который я завёл с целью писать всякие интересности связанные с Eclipse, за время моего отсутствия сильно увял, так и не успев распустится. Это печально. Сейчас я всё же хочу произвести очередную попытку наполнить сей ресурс полезной информацией, учитывая то, что кое какой материал у меня накопился за это время и я надеюсь он будет полезен публике. Более того, за это время к блогу присоединился ещё один автор, Kurill, который обещал способствовать развитию ресурса... Так что я тоже, с нетерпением жду новый интересных статей в этом блоге! ;-)

Ну а пока, предлагаю почитать, на мой взгляд, просто замечательную статью "Давайте посмотрим, что нового будет в Eclipse 3.5" сурового челябинского программиста про Eclipse 3.5 Galileo RC1.

вторник, Ноябрь 11, 2008

Word processor in the Eclipse

В последнее время стал замечать за собой, что при работе в обычных текстовых редакторах, таких как OOo Writer, какой-нибудь gedit и прочих (в vim, разве что я этого за собой не наблюдаю), я стал требовать от них тех функций и того окружения, которые есть в стандартном редакторе java в eclipse... А именно (на примере OOo Writer, к остальным нет смысла придираться):
  • Возврат к последнему месту изменения текста (Alt+Left в Eclipse) - вот иногда, бывает правишь большой текст и, бац, промахнулся мимо кнопки delete прям по кнопке end (ну вот косолапый я, что теперь?). Вернуться назад просто так не получается, приходится ползать по всему документу в поисках места от куда вылетел курсор. Наверно, можно нажать Ctrl+Z и чуток отменить написанное - курсор вернётся на место, а потом нажать Ctrl+Y... но мне кажется это как-то кривовато, хочется как в eclipse ;-);
  • Не хватает закладок на полях, на самом деле в OOo они есть и ими даже можно пользоваться (в том плане, что это вполне удобно при определённой сноровке), но всё равно хочется как в Eclipse. Тут дело даже не в том, что хочется и всё тут, а вот именно, что не хватает всяких приятных мелочей, которые начинаешь замечать только при их отсутствии - горячих клавиш, например, возможности быстро перемещаться от одной закладки к другой, нет отметок на полях и так далее;
  • Не хватает быстрого перехода от одной выделенной ошибки к другой (Ctrl+. и Ctrl+,);
  • Ну и вообще было бы очень вкусно, на мой взгляд, использование эклипсовских вьюх (ViewPart) с их великолепной возможностью располагаться в любых позах и любой последовательности. Например, мне не хватает возможности открыть сразу два документа, один в левой части экрана, другой - в правой (или один в верху, другой - внизу или вообще три или четыре сразу документа открыть, хотя это слишком)! Да это можно сделать, оконные менеджеры давно позволяют вытворять такие штуки с диалоговыми окнами, но черт возьми, эклипсавчане меня поймут - все эти окна - это всё фигня, хочу вьюхи и перспективы! ;-)
Да и вообще, если подключить фантазию и реализовать функционал OOo Writer (или вообще всего офиса) на платформе RCP - это ж, мне кажется, можно классного монстра сделать!..

На самом деле OpenOffice.org велик и могуч, в том виде в котором он есть. Весь пакет приложений создавался как альтернатива, ненавистному, MS Office, поэтому ребята двигаются своей дорогой, я лишь хочу пожелать им удачи в этом.

Возможно я просто стал излишне капризен по мелочам. Возможно. Но, всё же, думаю, что было бы очень не дурно иметь некоторый (пусть не полнофункциональный) текстовый редактор внутри Eclipse IDE - для написания технической документации по разрабатываемому проекту, например, или её прочтения, а также прочих будничных применений. И тут, конечно, нужно сказать, что такой текстовый редактор был бы удобен в первую очередь программисту, нежили простому офисному планктону, что может показаться странным - программисты не часто что-то пишут, кроме кода. Да, может быть некоторые вообще этого не делают, но для тех, кому всё же приходится работать с документами, я думаю, такая штука была бы очень интересна. Ну или как минимум приятна! :-)

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