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

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

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

namespace fruit;

var currentltemType:Namespace = fruit;

currentltemType var orange:String = «Round citrus fruit»;

вызовет такую ошибку:

Namespace was not found or is not a compile-time constant.

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

Аналогичным образом переменные не могут быть использованы для указания пространства имен в директиве use namespace. Мы познакомимся с этой директивой далее, в разд. «Открытые пространства имен и директива use namespace».

Пространства имен в качестве аргументов и возвращаемых значений методов

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

public function doSomething (n:Namespace):void { trace(n);

}

Этот код передает пространство имен fruit в метод doSomething ( ): doSomething(fruit):

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

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

Этот код определяет метод getNamespace ( ), который возвращает пространство имен fruit:

public function getNamespace ( ):Namespace { return fruit:

}

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

Пример использования значения пространства имен

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

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

Бегло просмотрите код в листинге 17.3, чтобы получить общее представление о программе. В данном примере пространства имен используются только в классах I terns и Kids Game, поэтому вы должны сосредоточить свое внимание на этих классах. Информацию о методиках, применяемых для создания пользовательского интерфейса в этом примере, можно найти в части П. Подробный анализ кода представлен сразу после листинга.

Листинг 17.3. Детская игра: пример использования значения пространства имен

// Файл fruit. as package {

public namespace fruit = «http://www. example. com/games/kidsgame/fruit»;

}

// Файл color. as package {

public namespace color = «http://www. example. com/games/kidsgame/color»;

}

// Файл Items. as package {

‘ // Простой класс для хранения данных, содержащий объекты Item для игры, public class Items { // Фрукты

fruit var orange:Item = new Item(«Orange», «fruit-orange. jpg», 1); fruit var apple:Item = new ItemC’Apple», «fruit-apple. jpg», 2);

// Цвета

color-var orange-.Item = new Item( «Orange», «color-orange. jpg», 3); color var purple:Item = new ItemCPurple», «color-purple. jpg», 4);

// Массивы, хранящие полные наборы элементов (то есть все фрукты // или все цвета)

fruit var itemSet:Array = [fruit::orange, fruit::apple]; color var itemSet:Array = [color::orange, color::purple];

// Массив пространств имен, представляющих

// типы наборов элементов в игре

private var itemTypes:Array = [color, fruit];

// Возвращает все элементы-фрукты, используемые в игре fruit function getltems ( ):Array { return fruit::itemSet. slice(0);

}

// Возвращает все элементы-цвета, используемые в игре color function getltems ( ):Array {

return color::itemSet. siice(O);

}

// Возвращает список доступных типов элементов, используемых в игре public function getltemTypes ( ):Аггау { return i temTypes. s1i се(0);

}

}

// Файл KidsGame. as package {

import flash. display.*;

import flash. events.*;

import flash. utils.*;

// Основной класс приложения для детской игры «Учусь читать», которое // демонстрирует основы использования пространств имен в языке ActionScript. // Игроку показывается картинка с цветом или фруктом и предлагается выбрать // название этого цвета или фрукта из списка вариантов, public class KidsGame extends Sprite { private var gameltems:Items; // Список всех элементов, используемых

// в игре

private var thisQuestionltem:Item; // Элемент для каждого вопроса private var questionScreen:QuestionScreen; // Пользовательский интерфейс

// Конструктор

public function KidsGame( ) { // Получаем элементы, используемые в игре (фрукты и цвета, // названия которых должен указать игрок) gameltems = new Items( ); // Отображаем первый вопрос newQuestion( );

}

// Создаем и отображаем новый случайный вопрос public function newQuestion ( ):void {

// Получаем полный список типов элементов (массив пространств имен)

var itemTypes:Array = gameltems. getItemTypes( );

// Случайным образом выбираем тип элемента (одно из пространств имен,

// на которые ссылается переменная itemTypes)

var randomltemType:Namespace = itemTypes[Math. floor(

Math. random( )*itemTypes.1ength)];

// Получаем элементы набора, выбранного случайным образом var items:Array = gameltems. randomltemType: -.getItems( );

// Случайным образом выбираем элемент для данного вопроса // из набора элементов

thisQuestionltem = iterns[Math. floor(Math. random( )*iterns. length)];

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

Глава 17. Пространства имен

// Удаляем предыдущий вопрос, если он существует if (questionScreen!= null) { removeChild(questionScreen);

}

// Отображаем новый вопрос

questionScreen = new QuestionScreen(this, items, thisQuestionltem); addChild(questionScreen);

}

// Обрабатываем ответ игрока public function submitGuess (guess:int) .-void { traceCGuess: » + guess + «, Correct: » + thisQuestionltem. id); if (guess == thisQuestionltem. id) { questi onScreen. di splayResult(«Correct!»); // Отключить кнопки ответа до тех пор, пока игрок не дождется // следующего вопроса. questionScreen. disable( );

// Подождать 3 секунды перед отображением следующего вопроса, var timer:Timer = new Timer(3000, 1); timer. addEventLi stener(TimerEvent. TIMER, doneResultDelay); timer. start( ); } else {

questionScreen. di spl ayResultC Incorrect. Please try again.»);

}

}

// Создает новый вопрос после того, как был получен // ответ на предыдущий.

private function doneResultDelay (e:TimerEvent):void {

newQuestion( ); } ‘

}

// Файл Item. as package {

// Простой контейнер данных, который хранит информацию об элементе, public class Item {

// Название элемента (например, «apple»)

public var name:String;

// Адрес URL, с которого загружается изображение, // представляющее элемент public var src:String;

// Уникальный идентификатор элемента, который используется // для обработки ответов игрока public var id:int;

// Конструктор

public function Item (name:String, src:String, id:int) { this. name = name;

this. src = src; this, id = id;

}

}

}

// Файл QuestionScreen. as package {

import flash. events.*;

import flash. display.*;

import flash. text.*;

import flash. net.*;

// Создает пользовательский интерфейс для вопроса public class QuestionScreen extends Sprite {

private var status:TextField;

private var game:KidsGame;

private var items:Array;

private var thisQuestionltem:Item;

// Конструктор

public function QuestionScreen (game:KidsGame,

items:Array.

Продолжение:

1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,

41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,

77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,

109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,

135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153

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

ThisQuestionltem:Item) { // Сохраняем ссылку на основной объект игры this. game = game;

// Собираем данные о вопросе this. items = items;

this. thisQuestionltem = thisQuestionltem;

// Помещаем вопрос на экран makeQuestion( );

}

// Создаем и отображаем интерфейс для вопроса public function makeQuestion ( ):void {

// Отображаем картинку для элемента

var imgLoader:Loader = new Loader( );

addChild(imgLoader);

imgLoader. load(new URLRequest(thisQuestionltem. src));

// Добавляем набор слов, которые может выбирать игрок,

// щелкая кнопкой мыши. Для упрощения будем отображать

// название каждого элемента в наборе.

var wordButton:WordButton;

for (var i:int = 0; i < items.length; i++) {

wordButton = new WordButton( );

wordButton. setButtonText(i terns[i].name);

wordButton. setID(items[i].id);

wordButton. у = 110 + i*(wordButton. height + 5);

wordButton. addEventLi stener(MouseEvent. CLICK, cli ckLi stener); addChild(wordButton);

}

// Создаем текстовое поле, в котором будет отображаться статус вопроса

status = new TextFieldC );

status. autoSize = TextFieldAutoSize. LEFT;

status. у = wordButton. у + wordButton. height + 10;

status. selectable = false;

addChild(status);

}

// Отображает сообщение в поле статуса public function displayResult (msg:String):void { status. text = msg;

}

// Выводит выбранное пользователем слово для данного вопроса public function disable ( ):void {

// Отключаем события мыши для всех потомков данного объекта Sprite.

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

MouseChildren = false;

}

// Реагируем на событие, вызванное щелчком кнопкой мыши на кнопке-слове

private function clickListener (е:MouseEvent):void { // Выбранный игроком вариант имеет идентификатор элемента, который был // присвоен объекту WordButton в методе makeQuestion( ). game. submitGuess(е. target. get IDC ));

}

}

}

// Файл WordButton. as package {

import flash. text.*;

import flash. display.*;

// Представляет на экране слово, на котором можно щелкнуть кнопкой мыши // (то есть доступный вариант ответа на вопрос). ID обозначает // идентификатор элемента, выбранного игроком (переменная Item. id), public class WordButton extends Sprite {

private var id:int; // Идентификатор элемента, представляемого // данной кнопкой

private var t:TextField;

// Конструктор

public function WordButton ( ) { t = new TextField( ); t. autoSize = TextFieldAutoSize. LEFT; t. border = true: t. background = true;

t. selectable = false; addChild(t);

buttonMode = true; mouseChildren = false;

}

// Присваивает текст, отображаемый на кнопке public function setButtonText (text:String):void { t. text = text;

}

// Присваивает идентификатор элемента, представляемого данной кнопкой public function setID (newID:int):void { id = newID:

}

// Возвращает идентификатор элемента, представляемого данной кнопкой public function getID ( ):int { return id;

}

}

}

Просмотрели код? Отлично, рассмотрим его более детально. Возможно, вы заметили, что определения пространств имен в игре не изменялись вообще с того момента, как они были представлены в листинге 17.1. Тем не менее существенно изменился класс Items, а также появилось несколько новых классов:

? KidsGame — основной класс приложения;

? I tem — предоставляет информацию о конкретном элементе игры;

? QuestionScreen — формирует пользовательский интерфейс для каждого вопроса;

? WordButton — представляет кнопку-слово на экране.

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

Поскольку сейчас наше внимание сосредоточено на пространствах имен, мы рассмотрим только классы Items и KidsGame. В качестве упражнения рассмотрите оставшиеся классы самостоятельно.

Для начала посмотрим, как изменился класс Items со времени его предыдущего представления в листинге 17.1. Во-первых, мы добавили две новые переменные fruit: : apple и color: : purple, представляющие элементы. Благодаря новым переменным каждая категория элементов для фруктов и цветов теперь состоит из двух элементов: апельсина и яблока для фруктов и оранжевого и фиолетового для цветов. Мы также заменили простые описания элементов из листинга 17.1 (например, Round citrus fruit) экземплярами класса Item. Экземпляры класса Item хранят название элемента, URL-адрес изображения этого элемента и его идентификатор. Следующий код демонстрирует измененные переменные, представляющие элементы. Как и в листинге 17.1, каждая переменная уточняется пространством имен, соответствующим множеству, которому принадлежит данный элемент.

fruit var orange:Item = new Item(«Orange», «fruit-orange. jpg», 1); fruit var apple:Item = new ItemCApple». «fruit-apple. jpg». 2);

color var orange:Item = new Item(«Orange», «color-orange. jpg», 3); color var purple:Item = new ItemC’Purple». «color-purple. jpg», 4);

Кроме того, в класс I terns добавлены два массива, предназначенные для управления элементами в виде групп. Каждый массив содержит полный список элементов своей группы (либо фруктов, либо цветов). Массивы присваиваются переменным с одним и тем же именем (itemSet), но уточняемым различными пространствами имен (fruit и color).

fruit var itemSet:Array = [fruit::orange, fruit::apple]; color var itemSet:Array = [color: :orange, color: .-purple];

Чтобы предоставить доступ другим классам к различным наборам элементов в игре, в Items определено два метода с одним и тем же локальным именем getltems ( ), которое уточняется различными пространствами имен fruit и color. Каждый метод get I terns ( ) возвращает копию набора элементов, соответствующего пространству имен данного метода. Таким образом, обратиться к подходящему набору элементов можно динамически, в зависимости от текущего типа вопроса (либо цвет, либо фрукт).

fruit function getltems ( ):Array { // Возвращает фрукты, return fruit::itemSet. siice(O):

}

color function getltems ( ):Array { // Возвращает цвета, return color::itemSet. slice(0);

}

Наконец, в классе Items определены переменная itemTypes и соответствующий метод-аксессор get ItemTypes ( ). Переменная itemTypes хранит список всех различных множеств элементов в игре. В нашей игре определено только два множества: фрукты и цвета, но в дальнейшем можно будет легко добавить новые множества. Каждое множество элементов соответствует пространству имен, поэтому переменная itemTypes представляет собой массив пространств имен. Метод get ItemTypes ( ) возвращает копию этого массива, предоставляя внешнему коду возможность централизованно получать официальный список типов элементов в игре.

// Переменная itemTypes

private var itemTypes.-Array = [color, fruit]:

// Метод getItemTypes( ) public function getltemTypes ( ):Array { return itemTypes. siice(O);

}

Это все, что касается изменений в классе Items. Теперь рассмотрим новый основной класс приложения KidsGame. В отличие от Items, класс KidsGame никогда не

использует идентификаторы пространств имен fruit и color напрямую. Вместо этого он обращается к указанным пространствам имен через метод экземпляра

getltemTypes ( ) класса Items.

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

Переменная gameltems класса KidsGame позволяет ему обращаться к игровым данным посредством объекта класса Items. При этом метод newQuestion ( ) класса KidsGame генерирует новый вопрос на основании данных, хранящихся в переменной gameltems. Метод newQuestion ( ) включает основную часть кода, связанного с использованием пространств имен. Именно эта часть интересует нас больше всего, поэтому рассмотрим данный код детально.

Напомним, что каждый вопрос отображает элемент одного из предопределенных наборов элементов, хранящихся в классе Items (fruit: ritemSet или color: ritemSet). Соответственно первая задача, которая стоит перед методом newQuestion ( ), — случайным образом выбрать набор элементов для генерируемого вопроса. Сначала мы получаем весь массив возможных наборов элементов (то есть пространств имен) из класса Items, используя метод gameltems. getltemTypes ( ):

var itemTypes:Array = gameItems. get ItemTypes( );

Затем мы случайным образом выбираем пространство имен из результирующего массива. Для удобства мы присваиваем выбранное пространство имен локальной переменной randomltemType.

var randomltemType:Namespace = itemTypes[Math. floor(

Math. random( )*itemTypes.1ength)];

Обратите внимание, что типом данных переменной randomltemType является тип Namespace, поскольку эта переменная ссылается на значение пространства имен. Как только будет выбран набор элементов (пространство имен) для вопроса, мы должны получить список существующих элементов из этого набора. Чтобы получить соответствующий массив элементов (либо фруктов, либо цветов), мы вызываем метод класса Items, который соответствует нашему выбранному пространству имен, — либо метод fruit: : getltems ( ), либо метод color: : get I terns ( ). Однако вместо того, чтобы обращаться к желаемому методу напрямую, мы динамически генерируем уточненный идентификатор метода, используя переменную randomltemType для определения пространства имен, как показано в следующем коде:

gameltems. randomltemType::get Items( )

Массив, возвращаемый методом, присваивается локальной переменной items: var items:Array = gameltems. randomltemType::get Items( ):

* •»

В предыдущем вызове метода обратите внимание, что поведение программы определяется контекстом программы. Эту особенность можно рассматривать как разновидность полиморфизма, которая основывается не на наследовании классов, а на произвольных группах методов и переменных, определяемых пространствами имен.

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

мы случайным образом выбираем элемент для отображения из массива элементов:

thisQuestionltem = items[Math. floor(Math. random( )*iterns. length)]:

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

// Удаляем предыдущий вопрос, если он существует if (questionScreen!= null) { removeChild(questionScreen);

}

// Отображаем новый вопрос

questionScreen = new QuestionScreen(this, items. thisQuestionltem): addChild(questionScreen);

Приведем код метода newQuestion ( ) еще раз. Обратите особое внимание на использование значений пространств имен в этом коде, поскольку мы не будем больше возвращаться к нему.

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

Public function newQuestion ( ):void { // Получаем полный список типов элементов (массив пространств имен) var itemTypes.-Array = gameltems. get ItemTypes ( ); // Случайным образом выбираем тип элемента (одно из пространств имен, // на которые ссылается переменная itemTypes) var randomltemType:Namespace = itemTypes[Math. floor(

Math. random( )*itemTypes.1ength)];

// Получаем элементы набора, выбранного случайным образом var items:Array = gameltems. randomltemType: -.get I terns ( );

// Случайным образом выбираем элемент для данного вопроса // из набора элементов

thisQuestionltem = iterns[Math. floor(Math. random( )*iterns. length)];

// Удаляем предыдущий вопрос, если он существует if (questionScreen!= null) { removeChild(questionScreen);

}

// Отображаем новый вопрос

questionScreen = new QuestionScreen(this, items, thisQuestionltem); addChi1d(questi onScreen);

}

Оставшаяся часть кода из листинга 17.3 относится к игровой логике и созданию пользовательского интерфейса, что в настоящее время не является нашей основной задачей. Как уже отмечалось ранее, вы должны самостоятельно изучить оставшийся код. Информацию о методиках создания пользовательского интерфейса можно найти в части II этой книги.

Что ж, это был хороший практический пример. Впереди нас ждет еще несколько примеров, однако сначала мы должны рассмотреть две фундаментальные концеп-

ции, относящиеся к пространствам имен: открытые пространства имен и пространства имен для модификаторов управления доступом.

Открытые пространства имен и директива use namespace

Помните простой класс Items из листинга 17.1?

package { public class Items { fruit var orange:String = «Round citrus fruit»; color var orange:String = «Color obtained by mixing red and yellow»;

public function Items ( ) { trace(fruit: -.orange); trace(color::orange);

}

}

}

Как уже говорилось, один из способов обращения к переменным orange в предыдущем коде заключается в применении уточненных идентификаторов, как показано ниже:

trace(fruit::orange); // Выводит: Round citrus fruit trace(color::orange); // Выводит: Color obtained by

// mixing red and yellow

Однако язык ActionScript предлагает еще один удобный инструмент для обращения к переменным, уточняемым пространствами имен: директиву use namespace. Директива use namespace добавляет указанное пространство имен в набор так называемых открытых пространств имен для определенной области видимости программы. Открытые пространства имен — это набор пространств имен, к которому обращается компилятор при попытке разрешить неуточненные ссылки. Например, если пространство имен п находится в наборе открытых пространств имен и компилятор встретит неуточненную ссылку на переменную р, то он автоматически проверит существование переменной п: : р.

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

Рассмотрим общий вид директивы use namespace:

use namespace идентификаторПространстваИмен

Здесь идентификаторПространстваИмен — это идентификатор пространства имен, которое должно быть добавлено в набор открытых пространств имен. Стоит отметить, что данный идентификатор должен быть константой на этапе компиляции, поэтому не может быть переменной, которая ссылается на значение пространства имен.

Посмотрим на примере предыдущего конструктора класса Items, как работает директива use namespace, обратившись напрямую к локальной переменной orange после того, как пространство имен fruit будет добавлено в набор

открытых пространств имен (эта операция также называется открытием пространства имен fruit).

public function Items ( ) { use namespace fruit; trace(orange);

}

Мы добавили пространство имен fruit в набор открытых пространств имей, поэтому, когда компилятор встретит следующий код:

trace(orange);

он автоматически проверит, существует ли уточненный идентификатор fruit: : orange. В нашем примере данный идентификатор существует, поэтому он будет использован вместо локального имени orange. Другими словами, в конструкторе класса Items этот код:

trace(fruit::orange); // Выводит: Round citrus fruit выполняет то же самое, что и следующий: use namespace fruit;

trace(orange); // Выводит: Round citrus fruit

Открытые пространства имен и область видимости

Каждая область видимости в программе на языке ActionScript имеет отдельный список открытых пространств имен. Пространство имен, открытое в определенной области видимости, будет открыто для нее, включая вложенные области, но при этом оно не будет открыто для остальных областей видимости. Открытое пространство имен будет доступно даже до инструкции use namespace (однако лучше всего помещать директиву use namespace в самом верху содержащего ее блока кода).

Напомним, что «область видимости» обозначает «область программы». В ActionScript для d ч каждого пакета, класса и метода определена уникальная область видимости. Условные 4 д]а4 операторы и операторы циклов не имеют собственных областей видимости.

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

В листинге 17.4 демонстрируется общий код, чтобы показать две различные области видимости со своими отдельными списками открытых пространств имен. Пояснения к коду приводятся в виде комментариев.

Листинг 17.4. Демонстрация открытых пространств имен

public class ScopeDemo { // Создаем пространство имен, private namespace nl = «http://www. example. com/nl»;

// Создаем две переменные, уточняемые пространством имен nl. nl var а:Stri ng = «а»; nl var b:String = «b»;

// Конструктор

public function ScopeDemo ( ) {

// Вызываем метод, который обращается к переменной nl::a. showA( );

}

public function showA ( ):void { // Эта неуточненная ссылка на переменную а полностью соответствует // уточненному идентификатору nl::a, поскольку следующая строка кода // открывает пространство имен nl. trace(a); // OK!

// Открываем пространство имен nl. use namespace nl;

// Неуточненная ссылка на переменную а // снова соответствует уточненному // идентификатору nl::a. trace(a); // ОК!

// Создаем вложенную функцию, function f ( ):void {

// Пространство имен nl остается открытым во вложенных областях

// видимости…

trace(a); // ОК! Соответствует n1::а.



Полезные ссылки
Случайные записи
  • 21.06.2011">Объективные стороны рестайлинга сайтов.
  • 18.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.77
  • 22.12.2011">Samsung производит процессоры A5 для Apple iPhone 4S и iPad 2
  • 12.03.2011">Руководство по actionscript. часть 3, стр. 136
  • 16.06.2010">Самоучитель по креативному веб-дизайну. Книга 4, стр.31
  • 16.06.2010">Самоучитель по креативному веб-дизайну. Книга 4, стр.29
  • 11.03.2011">Руководство по actionscript. часть 4, стр. 013
  • 18.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.93
  • 24.02.2011">Руководство по actionscript. часть 6, стр. 108
  • 10.08.2011">Торгуйте на Forex вместе с платформой MetaTrader 4
  • 21.03.2011">Руководство по actionscript. часть 2, стр. 042
  • 18.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.107
  • 25.02.2011">Руководство по actionscript. часть 6, стр. 090
  • 30.01.2011">Форматы растровой графики
  • 27.02.2011">Руководство по actionscript. часть 6, стр. 033
Опрос

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

View Results

Loading ... Loading ...