Руководство по actionscript. часть 3, стр. 136

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

group. х = 40; group. scaleY = .15; group. rotation = 15;

Изменения затрагивают дочерние экземпляры класса Shape, как показано на рис. 20.14.

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

// Создаем третий прямоугольник

var rect3;Shape = new ShapeC );

rect3.graphi cs.1i neSty1e(1);

rect3.graphi cs. begi nFi11(OxOOFFOO, 1);

rect3.graphics. drawRect(0, 0, 75, 50);

rect3.x = 25;

rect3.y = 35;

group. addChild(rect3);

На рис. 20.15 показан результат.

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

group. scaleY = 1; group. х = 0; group. rotation = 0;

На рис. 20.16 показан результат. Обратите внимание, что теперь размеры и позиция третьего прямоугольника соответствуют указанным значениям.

Руководство по actionscript. часть 3, стр. 137

Цветовые и координатные трансформации, осуществляемые через переменную экземпляра transform класса DisplayObject, также наследуются всеми потомками этого экземпляра. Например, следующий код применяет черную цветовую трансформацию к объекту group, в результате чего все три прямоугольника окрашиваются в сплошной черный цвет.

import f1 ash. geom. ColorTransform;

var blackTransform:ColorTransform = new ColorTransform( );

blackTransform. color = 0×000000;

group. transform. colorTransform = blackTransform;

Рис. 20.13. Два Рис. 20.14. Рис. 20.15. Третий Рис. 20.16.

прямоугольника Перемещение, прямоугольник Трансформации

в контейнере масштабирование удалены и вращение

I Подробную информацию о типах цветовых и координатных трансформаций, доступных 4 щ в языке ActionScript, можно найти в описании пакета flash. geom. Transform в справочнике —по языку ActionScript корпорации Adobe.

Трансформации, выполняемые над вложенными контейнерами, являются составными. Например, следующий код помещает прямоугольник в объект Sprite, который вложен в другой объект Sprite. Каждый из экземпляров класса Sprite будет повернут на 45°. В результате прямоугольник окажется повернутым на 90° (45 + 45).

// Создаем прямоугольник

var recti:Shape = new Shape( );

recti. graphi cs.1i neSty1e(1);

recti. graphics. beginFill(OxOOOOFF, 1);

rectl. graphics. drawRect(0. 0, 75, 50);

var outerGroup:Sprite = new Sprite( ); var innerGroup:Sprite = new Sprite( );

i nnerGroup. addChi1d(recti); outerGroup. addChi1d(i nnerGroup); innerGroup. rotation = 45; outerGroup. rotation = 45;

Обращение к экземпляру основного класса SWF-файла из потомков

В языке ActionScript 3.0 отображаемые потомки экземпляра основного класса SWF-файла могут получать ссылку на этот экземпляр через переменную экземпляра root класса DisplayObject. Например, рассмотрим код из листинга20.5, представляющий основной класс SWF-файла Арр. При выполнении этого кода среда Flash автоматически создает экземпляр класса Арр и выполняет его конструктор. Внутри конструктора два потомка экземпляра класса Арр (объект Sprite и объект Shape) обращаются к экземпляру класса Арр через переменную root.

Руководство по actionscript. часть 3, стр. 138

Листинг 20.5. Обращение к экземпляру основного класса SWF-файла из потомков

package { import flash. display.*; import flash. geom.*;

public class Арр extends Sprite { public function Арр ( ) { // Создаем потомков… var rect:Shape = new Shape( ); rect. graphi cs.1i neSty1e(1); rect. graphics. beginFi11(OxOOOOFF, 1); rect. graphics. drawRect(0, 0, 75, 50); var sprite;Sprite = new Sprite( ); sprite. addChild(rect); addChiId(spnte);

// Используем выражение DisplayObject. root для обращения // к данному экземпляру класса Арр trace(rect. root); // Выводит: [object Арр] trace(sprite. root); // Выводит: [object Арр]

}

}

}

Когда объект находится в списке отображения, но не является потомком экземпляра основного класса SWF-файла, его переменная stage возвращает ссылку на экземпляр класса Stage. Например, следующий код модифицирует класс Арр из листинга 20.5 таким образом, чтобы объект Sprite и его дочерний объект Shape добавлялись непосредственно в экземпляр Stage. Поскольку объекты Sprite и Shape не являются потомками экземпляра основного класса SWF-файла, их переменные root ссылаются на экземпляр класса Stage.

package { import flash. display.*; import flash. geom.*;

public class App extends Sprite { public function App ( ) { var rect:Shape = new Shape( ); rect. graphi cs.1i neSty1e(1); rect. graphi cs. begi nFi11(OxOOOOFF, 1); rect. graphics. drawRect(0, 0, 75, 50); var sprite:Sprite = new Sprite( ); sprite. addChild(rect);

// Добавляем дочерний объект к экземпляру класса Stage, // а не к данному экземпляру класса Арр stage. addChi1d(spri te);

trace(rect. root); // Отображает: [object Stage] trace(sprite. root); // Отображает: [object Stage]

Для объектов, которые находятся в списке отображения, но не являются потомками эк-м?’ а * земпляра основного класса SWF-файла, переменная экземпляра root класса DisplayObject 4 _3# тождественна его переменной экземпляра stage.

В первом SWF-файле, открытом средой выполнения Flash, переменной root всех отображаемых объектов, которые не находятся в списке отображения, присвоено значение null.

В SWF-файлах, которые загружаются другими SWF-файлами, значение переменной root устанавливается следующим образом:

? если отображаемые объекты являются отображаемыми потомками экземпляра основного класса, то переменная root ссылается на этот экземпляр, даже если экземпляр основного класса не находится в списке отображения;

? для отображаемых объектов, которые не являются отображаемыми потомками экземпляра основного класса и не находятся в списке отображения, переменной root присваивается значение null.

Руководство по actionscript. часть 3, стр. 139

Возрождение переменной _root

В языке ActionScript 2.0 и в более старых версиях языка глобальная переменная root ссылалась на самый верхний клип текущего уровня level. До появления языка ActionScript 3.0 обычный здравый смысл подсказывал, что использования переменной root следует избегать, поскольку ее значение было непостоянным (объект, на который ссылалась данная переменная, изменялся при загрузке SWF-файла в клип).

В языке ActionScript 3.0 глобальную переменную root заменяет переменная экземпляра root класса DisplayOb j ect. Переменная root класса DisplayOb j ect не подвержена непостоянству, которое было свойственно ее предку, и считается чистым, безопасным членом API отображения.

^4_ J Программисты на языке ActionScript, долгое время работавшие с предыдущими версиями щ языка и избегавшие применения устаревшей переменной _root, не должны испыты-— вать чувство страха или вины при использовании переменной экземпляра root класса DisplayObject в языке ActionScript 3.0.

Для чего нужна переменная level?

В языках ActionScript 1.0 и 2.0 функция loadMovieNum ( ) использовалась для размещения внешних SWF-файлов на независимых уровнях приложения Flash Player. Для обращения к каждому уровню использовался следующий формат: level/9, где п обозначает порядковый номер уровня в стеке уровней. В интерфейсе API среды выполнения Flash языка ActionScript 3.0 концепция слоев полностью отсутствует.

В языке ActionScript версии 3.0 ближайшим аналогом слоев являются дочерние объекты экземпляра класса Stage. Тем не менее, если в языках ActionScript 1.0 и 2.0 внешние SWF-файлы могли быть загружены непосредственно на уровень level, в языке ActionScript 3.0 внешние SWF-файлы не могут быть загружены непосредственно в список дочерних объектов экземпляра класса Stage. Вместо этого, чтобы добавить внешний SWF-файл в список дочерних объектов экземпляра класса Stage, мы должны сначала загрузить его с помощью объекта Loader, а затем

поместить его в экземпляр класса Stage через вызов метода stage. addChild ( ), как показано в следующем коде:

var loader:Loader = new Loader( );

1 oader. 1 oad(new URLRequest(«newContent. swf»));

stage. addChild(loader);

Более того, в языке ActionScript 3.0 невозможно удалить все содержимое из приложения Flash Player, выполнив выгрузку уровня level0. Код наподобие следующего больше не является допустимым:

// Очистить все содержимое в приложении Flash Player. // Исключено в языке ActionScript 3.0.

unloadMovieNum(O):

Ближайшей заменой выражения unloadMovieNum(0) в языке ActionScript3.0 является следующее выражение:

stage. removeChi1dAt(0):

Выражение stage. removeChildAt (0) удаляет первый дочерний объект экземпляра класса Stage из списка отображения, но не обязательно удаляет его из программы. Если в программе существуют другие ссылки на этот дочерний объект, он продолжит свое существование, при этом его можно повторно добавить в любой другой контейнер. Как было показано в подразд. «Удаление элементов из памяти» этого раздела, чтобы полностью удалить отображаемый объект из программы, необходимо не только удалить объект из контейнера, но и удалить все ссылки на него. Более того, вызов метода stage. removeChildAt (0) затрагивает только первый дочерний объект экземпляра класса Stage; другие дочерние объекты не удаляются из списка отображения (в отличие от вызова функции unloadMovieNum (0) в языках ActionScript 1.0 и 2.0, которая удаляет содержимое со всех уровней level). Чтобы удалить все дочерние объекты экземпляра класса Stage, используется следующий код внутри объекта, находящегося на глубине 0 экземпляра класса Stage:

while (stage. numChildren > 0) { stage. removeChi1dAt(stage. numChi1dren-1); // Когда удаляется последний дочерний объект, переменной stage // присваивается значение null, поэтому завершаем цикл if (stage == null) { break:

}

}

Подобным образом следующий устаревший код, который очищает приложение Flash Player от всего содержимого и затем помещает файл newContent. swf на уровень _level 0, больше не является допустимым:

1 oadMovieNum(«newContent. swf», 0);

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

Руководство по actionscript. часть 3, стр. 140

События контейнеров

Мы уже знаем, как использовать методы addChi 1 d ( ) и addChi IdAt ( ) для добавления нового отображаемого дочернего объекта в объект DisplayOb j ectContainer. Вспомним обобщенный код:

// Метод addChild( )

некийКонтейнер. addChi 16(новыйРебенок)

II Метод addChi1dAt( )

некийКонтейнер. addChi1d(новыйРебенок, глубина)

Мы также знаем, что существующие дочерние отображаемые объекты могут быть удалены из объекта Di splayOb j ectContainer с помощью методов removeChild ( ) и removeChildAt ( ). Опять же вспомним следующий обобщенный код:

// Метод removeChild( )

некийКонтейнер. removeChi1й(ребенокДляУдаления) II Метод removeChi1dAt( )

некийКонтейнер. геи\о\/еШ~\6№(глубинаРебенкаДляУдаления)

Наконец, мы знаем, что существующий дочерний отображаемый объект может быть удален из контейнера путем перемещения этого объекта в другой контейнер либо с помощью метода addChild ( ), либо с помощью метода addChildAt ( ). Вот этот код:

// Добавление объекта ребенок в контейнер некийКонтейнер некийКонтейнер. addChi1б(ребенок) ,

// Удаление объекта ребенок из контейнера некийКонтейнер путем // его перемещения в контейнер некийДругойКонтейнер некийДругойКонтейнер. addChi1d{ребенок)

Каждая из этих операций добавления и удаления дочерних объектов сопровождается внутренним событием среды выполнения Flash — Event. ADDED или Event. REMOVED. В следующих трех разделах рассматривается, как эти два события используются в программировании экранного вывода.

I Для изучения следующих разделов вам потребуется хорошее понимание системы иерар-К* 4 „ хической диспетчеризации событий языка ActionScript, рассматриваемой в гл. 21. Если вы еще не до конца знакомы с иерархической диспетчеризацией событий, прочтите гл. 21 перед тем, как приступить к изучению следующих разделов.

Руководство по actionscript. часть 3, стр. 141

События Event. ADDED и Event. REMOVED

После того как новый дочерний отображаемый объект добавляется в объект DisplayObjectContainer, среда Flash выполняет диспетчеризацию события Event. ADDED, получателем которого является новый дочерний объект. Подобным образом, когда существующий дочерний отображаемый объект удаляется из объекта DisplayOb j ectContainer, среда Flash выполняет диспетчеризацию события Event. REMOVED, получателем которого является удаленный дочерний объект.

Как будет рассмотрено в гл. 21, когда при диспетчеризации получателем события является объект в иерархии отображения, уведомление об этом событии получают данный объект и все его предки. Следовательно, когда возникает событие Event. ADDED, уведомление о добавленном дочернем объекте получают сам объект, его новый родительский контейнер и все предки данного контейнера. Подобным образом, когда возникает событие Event. REMOVED, уведомление об удаленном дочернем объекте получают сам объект, его старый родительский контейнер и все предки данного контейнера. Таким образом, события Event. ADDED и Event. REMOVED могут использоваться двумя различными способами:

? экземпляр класса DisplayOb j ectContainer может использовать эти события, чтобы определить, когда у него появляется или теряется отображаемый потомок;

? экземпляр класса Di spl а у Ob j ect может использовать данные события, чтобы определить, когда он будет добавлен в родительский контейнер или удален из него.

Рассмотрим обобщенный код, который демонстрирует описанные сценарии, начиная с контейнера, определяющего факт появления нового потомка.

Сначала мы создадим два объекта Sprite: один из них будет играть роль контейнера, а другой — дочернего объекта:

var container:Sprite = new Sprite( ); var child:Sprite = new Sprite( ):

Теперь мы создадим метод-приемник addedLi stener ( ), который будет регистрироваться в объекте container для получения событий Event. ADDED:

private function addedListener (e:Event):void { trace(«Added was triggered»):

}

После этого мы регистрируем метод addedLi stener ( ) в объекте container: contai пег. addEventLi stener(Event. ADDED, addedLi stener); Наконец, мы добавляем объект child в объект container: contai пег. addChi1d(chi1d);

При выполнении предыдущего кода среда Flash выполняет диспетчеризацию события Event. ADDED, получателем которого является объект child. В результате, поскольку объект container является отображаемым предком объекта child, на фазе всплытия события будет вызвана функция addedLi stener ( ), зарегистрированная в объекте container (дополнительную информацию по фазе всплытия можно найти в гл. 21).

I Когда событие Event. ADDED вызывает приемник события на фазе захвата или всплы-& d т тия’ МЬ| знаем/ что У объекта, в котором зарегистрирован приемник, появился новый -^-3?«4 отображаемый потомок.

Теперь добавим новый дочерний объект в объект child, превратив container в гордого прародителя:

var grandchild:Sprite = new Sprite( ); chi1d. addChi1d(grandchiId);

При выполнении предыдущего кода среда Flash снова осуществляет диспетчеризацию события Event. ADDED, получателем которого на этот раз является объект grandchild, и на фазе всплытия вновь вызывается метод addedLi stener ( ). Поскольку приемник вызван на фазе всплытия, мы знаем, что у объекта container появился новый потомок, но не уверены, является ли этот потомок непосредственным ребенком объекта container. Чтобы определить это, мы проверяем, совпадает ли значение переменной parent объекта child с объектом container, как показано в следующем коде:

private function addedListener (e:Event):void { // Помните, что переменная Event. currentTarget ссылается на объект, // в котором зарегистрирован выполняемый в настоящий момент приемник, -// в данном случае, на объект container. Помните также, что переменная // Event. target ссылается на получатель события, в данном случае -// на объект grandchild.

Руководство по actionscript. часть 3, стр. 142

If (DisplayObject(e. target. parent) == e. currentTarget) {

traceCA direct child was added»); } else {

trace(«A descendant was added»);

}

}

Продолжая работать с нашим примером, снова сделаем объект container ребенком, добавив его (и соответственно два его потомка) в экземпляр класса Stage:

stage. addChild(container);

При выполнении предыдущего кода среда Flash снова осуществляет диспетчеризацию события Event. ADDED, получателем которого является объект container. И снова вызывается метод addedListener ( ) — на этот раз на фазе получения, а не на фазе всплытия.

Когда событие Event. ADDED вызывает приемник события на фазе получения, мы знаем, что объект, в котором зарегистрирован приемник, был добавлен в родительский контейнер.

Чтобы различать ситуации, когда объект container приобретает нового потомка и когда сам объект container добавляется в родительский контейнер, мы проверяем текущую фазу события, как показано в следующем коде:

private function addedListener (e:Event):void { // Если этот приемник был вызван на фазе захвата или всплытия… if (е. eventPhase!= EventPhase. AT_TARGET) {

// …контейнер получил нового потомка

traceC’new descendant: » + е. target); } else {

// …в противном случае контейнер был добавлен к новому родителю traceC’new parent: » + DisplayObject(е. target).parent);

Теперь перейдем к событию Event. REMOVED. Оно работает аналогично событию Event. ADDED, но его диспетчеризация выполняется при удалении объектов, а не при их добавлении.

Руководство по actionscript. часть 3, стр. 143

Следующий код регистрирует приемник события Event. REMOVED с именем removedListener ( ) в объекте container для события Event. REMOVED:

contaiпег. addEventListener(Event. REMOVED, removedListener);

Теперь удалим потомка из объекта container:

chi1d. removeChi1d(grandchiId)

При выполнении предыдущего кода среда Flash осуществляет диспетчеризацию события Event. REMOVED, получателем которого является объект grandchild, и метод removedListener ( ) вызывается на фазе всплытия.

Далее следующий код удаляет сам объект container из экземпляра класса

Stage:

stage. removeChild(contaiпег)

При выполнении приведенного кода среда Flash осуществляет диспетчеризацию события Event. REMOVED, получателем которого является объект container, и метод removedListener ( ) вызывается на фазе получения.

Как и в случае с методом addedListener ( ), в методе removedListener ( ) мы можем различать ситуации, когда объект container теряет потомка и когда сам объект container удаляется из своего родительского контейнера, проверяя текущую фазу события, как показано в следующем коде:

private function removedListener (e:Event):void { // Если этот приемник был вызван на фазе захвата или на фазе всплытия… if (е. eventPhase!= EventPhase. ATJARGET) { // …из контейнера удаляется потомок

traceCa descendant was removed from container: » + e. target); } else {

// …в противном случае контейнер удаляется из своего родителя trace(«contaiпег is about to be removed from its parent: » + DisplayObject(e. target).parent);

}

}

В листинге 20.6 представлены предыдущие примеры кода для событий Event. ADDED и Event. REMOVED в контексте тестового класса ContainmentEventDemo. Мы рассмотрим реальные примеры использования событий контейнеров в двух следующих разделах.

Руководство по actionscript. часть 3, стр. 144

Листинг 20.6. Демонстрация событий контейнера

package { import flash. display.*; лщугЪ f \ ash. ем ents.*;

public class ContainmentEventDemo extends Sprite { public function ContainmentEventDemo ( ) { // Создаем объекты Sprite

var container:Sprite = new Sprite( ); var child:Sprite = new Sprite( ); var grandchild:Sprite = new Sprite( );

// Приступаем к приему событий Event. ADDED и Event. REMOVED contai ner. addEventLi stener(Event. ADDED, addedLi stener); contai ner. addEventLi stener(Event. REMOVED, removedLi stener);

// Добавляем объект child в объект container container. addChild(child); // Вызывает метод addedListener( )

// на фазе всплытия

// Добавляем объект grandchild в объект child child. addChild(grandchild); // Вызывает метод addedListener( )

// на фазе всплытия

// Добавляем объект container в экземпляр класса-Stage stage. addChild(container); // Вызывает метод addedListener( )

// на фазе получения

// Удаляем объект grandchild из объекта child child. removeChild(grandchiId) // Вызывает метод removedListener( )

// на фазе всплытия

// Удаляем объект container из экземпляра класса Stage stage. removeChild(container) // Вызывает метод removedListener( )

// на фазе получения

}

// Обрабатывает события Event. ADDED

private function addedListener (e:Event):void {

if (e. eventPhase!= EventPhase. AT_TARGET) { traceCcontainer has a new descendant: » + e. target);

} else {

trace(«container was added to a new parent: » + DisplayObject(e. target).parent);

}

}

// Обрабатывает события Event. REMOVED

private function removedListener (e:Event):void {

if (e. eventPhase 1= EventPhase. ATTARGET) { traceCa descendant was removed from container: » + e. target);

} else {

trace(«container was removed from its parent: » + DisplayObject(e. target).parent);

}

}

}

// В результате выполнения приложения ContainmentEventDemo // выводятся следующие строки:

container has a new descendant: [object Sprite] container has a new descendant: [object Sprite] container was added to a new parent: [object Stage] a descendant was removed from container: [object Sprite] container was removed from its parent: [object Stage]

Реальный пример использования событий контейнера

Теперь, когда известно, как работают события Event. ADDED и Event. REMOVED в теории, рассмотрим, как можно использовать их в реальном приложении. Предположим, что мы создаем класс IconPanel, который управляет визуальным расположением графических значков. Класс IconPanel используется в качестве одной из частей большего оконного компонента в интерфейсе, основанном на оконном представлении. Всякий раз при добавлении нового или удалении существующего значка из объекта IconPanel этот объект исполняет алгоритм по размещению значков. Чтобы определить моменты добавления и удаления дочерних значков, объект IconPanel регистрирует приемники для событий Event. ADDED и Event. REMOVED.

Руководство по actionscript. часть 3, стр. 145

В листинге 20.7 представлен код класса IconPanel, который намеренно был упрощен, чтобы продемонстрировать использование событий Event. ADDED и Event. REMOVED. Обратите внимание, что приемники событий Event. ADDED и Event. REMOVED выполняют код по размещению значков только в том случае, когда объект IconPanel приобретает нового или теряет существующего непосредственного ребенка. Код по размещению значков не выполняется в следующих ситуациях:

? когда объект IconPanel приобретает или теряет потомка, который не является непосредственным ребенком;

? если сам объект IconPanel добавляется в родительский контейнер.

Листинг 20.7. Размещение значков в классе IconPanel

package { import flash. display.*; import flash. events.*;

public class IconPanel extends Sprite { public function IconPanel ( ) { addEventLi stener(Event. ADDED. addedListener); addEventLi stener(Event. REMOVED. removedLi stener);

}

public function updateLayout ( ):void { // Выполняет алгоритм размещения значков (код не приводится)

}

// Обрабатывает события Event. ADDED private function addedListener (e:Event):void { if (DisplayObject(e. target. parent) == e. currentTarget) {

updateLayout( );

// Обрабатывает события Event. REMOVED private function removedListener (e:Event):void { if (DisplayObject(e. target. parent) == e. currentTarget) updateLayout( );

}

}

События ADDED TO STAGE и REMOVED J=ROM_STAGE

Как мы уже знаем из двух приведенных выше разделов, события Event. ADDED и Event. REMOVED возникают, когда экземпляр класса DisplayObject добавляется в экземпляр класса DisplayObjectContainer или удаляется из него. Однако по событиям Event. ADDED и Event. REMOVED нельзя определить, находится данный объект в настоящий момент в списке отображения или нет. Чтобы определить, когда экземпляр класса DisplayObject добавляется в список отображения или удаляется из него, используются события Event. ADDED_TO_STAGE и Event. REMOVED FROM STAGE, которые были добавлены в API отображения, начиная с приложения Flash Player 9.0.28.0.



Полезные ссылки
Случайные записи
  • 13.03.2011">Руководство по actionscript. часть 3, стр. 104
  • 09.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.169
  • 11.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.16
  • 06.07.2011">Acer выпустила нетбук с Android
  • 28.02.2011">Руководство по actionscript. часть 6, стр. 018
  • 03.06.2010">Самоучитель по креативному веб-дизайну. Книга 3, стр.58
  • 10.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.87
  • 26.02.2011">Руководство по actionscript. часть 6, стр. 072
  • 21.03.2011">Руководство по actionscript. часть 2, стр. 032
  • 02.06.2010">Самоучитель по креативному веб-дизайну. Книга 3, стр.109
  • 16.03.2011">Руководство по actionscript. часть 3, стр. 007
  • 07.03.2011">Руководство по actionscript. часть 4, стр. 120
  • 03.06.2010">Самоучитель по креативному веб-дизайну. Книга 3, стр.74
  • 23.02.2011">Руководство по actionscript. часть 7, стр. 029
  • 14.03.2011">Руководство по actionscript. часть 3, стр. 067
Опрос

Какие цвета вы предпочитаете?

View Results

Loading ... Loading ...