Паттерн Command (Команда)

Название и классификация паттерна

Команда - паттерн поведения объектов.

Назначение паттерна Command

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

Используйте паттерн Command, если:

  • система управляется событиями. При появлении такого события (запроса) необходимо выполнить определенную последовательность действий;
  • необходимо параметризировать объекты выполняемым действием, ставить запросы в очередь или поддерживать операции отмены (undo) и повтора (redo) действий;
  • нужен объектно-ориентированный аналог функции обратного вызова в процедурном программировании.

Пример событийно-управляемой системы - приложение с пользовательским интерфейсом. При выборе некоторого пункта меню пользователем вырабатывается запрос на выполнение определенного действия (например, открытия файла).

Описание паттерна Command

Паттерн Command преобразовывает запрос на выполнение действия в отдельный объект-команду. Такая инкапсуляция позволяет передавать эти действия другим функциям и объектам в качестве параметра, приказывая им выполнить запрошенную операцию. Команда - это объект, поэтому над ней допустимы любые операции, что и над объектом.

Интерфейс командного объекта определяется абстрактным базовым классом Command и в самом простом случае имеет единственный метод execute(). Производные классы определяют получателя запроса (указатель на объект-получатель) и необходимую для выполнения операцию (метод этого объекта). Метод execute() подклассов Command просто вызывает нужную операцию получателя.

В паттерне Command может быть до трех участников:

  • клиент, создающий экземпляр командного объекта;
  • инициатор запроса, использующий командный объект;
  • получатель запроса.

Структура паттерна Command

Структура паттерна Command показана на рис. 63.

Сначала клиент создает объект ConcreteCommand, конфигурируя его получателем запроса. Этот объект также доступен инициатору. Инициатор использует его при отправке запроса, вызывая метод execute(). Этот алгоритм напоминает работу функции обратного вызова в процедурном программировании - функция регистрируется, чтобы быть вызванной позднее.

Паттерн Command отделяет объект, инициирующий операцию, от объекта, который знает, как ее выполнить. Единственное, что должен знать инициатор, это как отправить команду. Это придает системе

receiver->action();

Рис. 63. UML-диаграмма паттерна Команда

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

Участники

Command - Команда: объявляет интерфейс для выполнения операции.

ConcreteCommand - конкретная Команда: определяет связь между объектом-получателем Receiver и действием; реализует операцию Execute путем вызова соответствующих операций объекта Receiver.

Client - клиент: создает объект класса ConcreteCommand и устанавливает его получателя.

Invoker - инициатор: обращается к команде для выполнения запроса.

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

Отношения

Клиент создает объект ConcreteCommand и устанавливает для него получателя.

Инициатор Invoker сохраняет объект ConcreteCommand.

Инициатор отправляет запрос, вызывая операцию команды Execute. Если поддерживается отмена выполненных действий, то ConcreteCommand перед вызовом Execute сохраняет информацию о состоянии, достаточную для выполнения отката.

aReceiver aClient

Г"| newCommand(aReceiver)

StoreCommand(aCommand)

Рис. 64. UML-диаграмма последовательностей паттерна Команда

Объект ConcreteCommand вызывает операции получателя для выполнения запроса.

На рис. 64 видно, как Command разрывает связь между инициатором и получателем (а также запросом, который должен выполнить последний).

Результаты применения паттерна Команда

Команда разрывает связь между объектом, инициирующим операцию, и объектом, имеющим информацию о том, как ее выполнить.

Команды - это самые настоящие объекты. Допускается манипулировать ими и расширять их точно так же, как в случае с любыми другими объектами.

Из простых команд можно собирать составные. В общем случае составные команды описываются паттерном Компоновщик.

Добавлять новые команды легко, поскольку никакие существующие классы изменять не нужно.

Реализация паттерна Command

Рассмотрим реализацию паттерна Command на примере игры «Шахматы». Имитируем возможность выполнения следующих операций:

  • создать новую игру;
  • открыть существующую игру;
  • сохранить игру;
  • сделать очередной ход;
  • отменить последний ход.

void open(string file) { cout

void save(string file) { cout

void make_move(string move) { cout

string getPlayerInput(string prompt) { string input; cout > input; return input;

// Базовый класс class Command {

virtual ~Command() 0 virtual void execute() = 0; protected:

Command(Game* p): pgame(p) {} Game * pgame;

class CreateGameCommand: public Command

CreateGameCommand(Game * p): Command(p) {} void execute() { pgame->create();

class OpenGameCommand: public Command

OpenGameCommand(Game * p) : Command(p) {} void execute() { string file_name;

file_name = getPlayerInput("Enter file name:"); pgame->open(file_name);

class SaveGameCommand: public Command

SaveGameCommand(Game * p) : Command(p) {} void execute() { string file_name;

file_name = getPlayerInput("Enter file name:"); pgame->save(file_name);

class MakeMoveCommand: public Command

MakeMoveCommand(Game * p): Command(p) {} void execute() {

// Сохраним игру для возможного последующего отката pgame->save("TEMP F1LE"); string move;

move = getPlayerInput("Enter your move:"); pgame->make_move(move);

class UndoCommand: public Command

UndoCommand(Game * p) : Command(p) {} void execute() {

// Восстановим игру из временного файла pgame->open("TEMP_FILE");

// Имитация действий игрока vector v;

// Создаем новую игру

v.push_back(new CreateGameCommand(&game));

// Делаем несколько ходов

v.push_back(new MakeMoveCommand(&game));

// Последний ход отменяем v.push_back(new UndoCommand(&game));

// Сохраняем игру

v.push_back(new SaveGameCommand(&game));

for (size_t i=0; i execute();

for (size_t i=0; i

Вывод программы:

Save game in TEMPFILE Enter your move: E2-E4 Make move E2-E4 Save game in TEMP FILE Enter your move: D2-D3 Make move D2-D3 Open game from TEMP_FILE Enter file name: gamel.sav Save game in game 1 .sav

Достоинства паттерна Command

Придает системе гибкость, отделяя инициатора запроса от его получателя.

Родственные паттерны

Паттерн Компоновщик можно использовать для реализации макрокоманд.

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

Команда, которую нужно копировать перед помещением в список истории, ведет себя, как Прототип.

При одновременном выделении нескольких объектов на панели свойств появляются кнопки со следующими командами формирования объектов:

ü Weld (Объединение). Позволяет создать новую фигуру путем объединения двух или более перекрывающихся объектов. Исходные объекты автоматически удаляются. Для заливки нового объекта используется заливка верхнего объекта.

ü Trim (Исключение). Удаляется та часть объекта, которая перекрывает другой объект. Исходные объекты удаляются

ü Intersect (Пересечение). Создает новый объект, образованный из области перекрытия объектов. Исходные объекты сохраняются.

ü Simplify (Упрощение). Позволяет удалять все невидимые, перекрытые другими объектами части.

ü Front Minus Back (Удаление по заднему плану). В результате выполнения команды остается та часть верхней фигуры, которая ничего не перекрывала.

ü Back Minus Front (Удаление по переднему плану). В результате выполнения команды остается та часть нижней фигуры, которую ничто не перекрывало.

Более полный контроль над формированием фигур можно осуществлять, используя докер Shaping (Формирование). Здесь дополнительно можно установить параметры для сохранения исходных или целевых объектов после выполнения команды.

ü если установлен флажок Source Objects (Исходные объекты), то после выполнения команды останется тот объект, который был выделен до выделения команды;

ü при установке флажка Target Object (s) (Целевые объекты) останется тот объект, к которому была применена команда Исключение, Объединение или Пересечение.

Инструмент Knife (Лезвие)

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

ü Auto Close On Cut (Автозамыкание после разреза). После разреза части объекта становятся самостоятельными объектами.

Инструмент Eraser (Ластик)

С его помощью можно интерактивно стирать отдельные участки. Инструмент расположен в наборе инструментов на одной кнопке с инструментом Shape (Форма). На панели свойств настраиваются:

ü Erase Thickness (Ширина ластика) от 0,001 до 100 дюймов

ü Auto reduced On Erase (Сокращение числа узлов после стирания) ‑ снижает сложность фигуры после стирания отдельных ее фрагментов путем уменьшения количества узлов стираемой области

ü Circle/Square (Форма ластика) может быть круглой или квадратной

Инструмент Smudge (Размазывающая кисть)

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

ü Nb Size (Толщина острия). По умолчанию - 0,1 дюйм. Диапазон от 0,03 до 2 дюймов.

ü Использование пера с нажимом. Используется при работе с графическим планшетом.

ü Add Dryout to the effect (Интенсивность). Определяет постепенное изменение размера мазка в соответствии со скоростью перетаскивания указателя мыши. Диапазон от -10 до 10. При значении 0 эффект не проявляется.

ü Fixed value for title setting (Округлость острия). Контролирует форму мазка. Измеряется в градусах. Может принимать значения от 15 (плоское острие) до 90 (эллиптическое острие).

ü Fixed value for bealing setting (Поворот мазка). Мазок располагается под заданным углом.

Практическая работа

Упражнение Использование команд формирования объектов

1. Нарисуйте какие-либо объекты. Расположите их так. чтобы они перекрывали друг друга.

2. Откройте докер Shaping (Windows‑Docker‑Shaping или Arrange‑Shaping)/

3. В раскрывающемся списке в верхней части окна Shaping выберите команду Weld (Объединение)

4. Выделите один из перекрывающихся объектов - он будет исходным для выполнения команды

5. В докере Shaping в группе Leave Original (Сохранять оригинал) выберите, какие объекты должны остаться после выполнения команды - исходный, целевой или оба. Для выполнения команды нажмите кнопку Apply (в нижней части докера). Указатель мыши при этом примет форму жирной стрелки.

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

Повторите задания пунктов 1-6 для команд Trim (Исключение) и Intersect (Пересечение).

Упражнение Применение инструмента Knife (Лезвие)

1. Создайте на странице документа какой-либо объект и выберите инструмент Knife (Лезвие) в наборе инструментов.

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

3. Создайте еще один объект. Для разреза его по произвольной траектории после первого щелчка на границе объекта протаскивайте указатель инструмента к другой точке границы по произвольной траектории, дойдя до границы, отпустите кнопку мыши

В начальной и конечной точке разреза указатель инструмента должен принимать вертикальное положение!

Упражнение Применение инструмента Eraser (Ластик)

1. Создайте на странице документа какой-либо объект и выделите его инструментом Pick (Выбор).

2. Выберите в наборе инструментов инструмент Eraser (Ластик). Мысленно определите область фигуры, которую вы хотите удалить. На панели свойств задайте форму и ширину инструмента.

3. Установите указатель в выбранном месте и дважды щелкните кнопкой мыши. Фрагмент объекта, соответствующий форме и ширине ластика, будет удален.

4. Теперь сотрите часть объекта, перетаскивая указатель произвольным образом внутри объекта. Как только кнопка мыши будет отпущена, процесс удаления завершится.

5. Для удаления прямолинейного фрагмента можно щелкнуть указателем сначала в начальной точке, а затем - в конечной точке линии.

6. Для стирания ломаной линии инструментом Erase используется следующая последовательность действий:

ü Щелкните начальную точку ломаной линии и ведите указатель мыши инструмента к следующему- узлу (за ним потянется пунктирная линия), дойдя до узла - нажмите клавишу Tab

ü затем ведите указатель к следующему узлу и снова нажимайте клавишу Tab для удаления линии по траектории движения и так далее, пока не удалите необходимый фрагмент линии или всю линию целиком;

ü в конце процедуры нажмите левую кнопку мыши - стирание закончится.

Упражнение 4 Применение инструмента Smudge (Размазывающая кисть)

1. Создайте или выделите фигуру, к которой будет применен инструмент Smudge . Если это -динамическая фигура (прямоугольник, многоугольник, эллипс и т.п.). то обратите ее контур в кривые Ctrl+Q .

2. Выберите инструментSmudge . на панели инструментов установите толщину кисти и другие свойства.

3. Чтобы начать «размазывание», перетаскивайте указатель инструмента Smudge через контур фигуры. Обратите внимание, что каждый раз при пересечении контура он меняет свою форму в соответствии с установленными параметрами. Процесс «размазывания» может продолжаться сколь угодно долго до получения нужного эффекта.

Упорядочивание объектов

Команды группирования

При одновременном выделении более одного объекта в строке свойств появляются следующие команды для группирования объектов:

Группировать (сгруппированные объекты выделяются как один) ‑ кнопка Group на панели свойств доступна в случае одновременного выделения двух или более объектов, команда Group из контекстного меню или сочетание клавиш <Ctrl+G >. Группа ведет себя как единый объект, т.е. любые изменения сделанные по отношению к группе распространяются на все объекты внутри группы. Каждый объект группы называется дочерним объектом. Объект в группе выделяется инструментом Pick с зажатой клавишей <CTRL >. Одновременно можно выделить только один объект в группе.

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

Существуют общие команды - команды, которые не имеют объектной специфики или служат для выполнения действий с объектами, которые не используют стандартные команды.

Также команды могут существовать и у отдельных объектов конфигурации. Они служат для выполнения операций, связанных именно с этим объектом.

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

Действия, выполняемые командой, описываются на встроенном языке в модуле команды.

Полезные ссылки:

  • Объекты конфигурации,
  • Средства разработки.

Команда (Command)

Команда - это действие, которое пользователь может выполнить в программе. Все команды можно классифицировать несколькими способами.

Стандартные команды и команды, созданные разработчиком

По отношению к тому, каким образом команда появилась в конфигурации, все команды можно разделить на:

  • Стандартные,
  • Созданные разработчиком.

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

Например, справочник Контрагенты может поставлять команды Контрагенты , Контрагент: создать и Контрагенты: создать группу .

Разработчик может сам создать произвольные команды в конфигурации. Он может добавить объект Команда в ветку Общие , добавить объект Команда в конкретный объект конфигурации или описать команду в виде процедуры на встроенном языке в конкретной форме. Подробнее...

Например, могут быть добавлены общие команды УстановитьСканерШтрихкодов , НастроитьСканерШтрихкодов и другие.

Навигационные команды и команды действий

По отношению к тому, что является результатом выполнения команды, все команды можно разделить на:

  • Навигационные команды,
  • Команды действий.

Навигационные команды открывают формы в текущем окне. Как правило, таким образом выполняется переход к каким-либо спискам. Подробнее...

Например, навигационная команда Склады откроет список складов в основном окне.

В результате выполнения команды действия открывается вспомогательное окно. Как правило таким образом выполняется переход к форме объекта или к форме отчета/обработки. Подробнее...

Например, команда действия Склад откроет вспомогательное окно для редактирования данных нового склада.

Независимые и параметризуемые команды

По отношению к своему внутреннему устройству, все команды можно разделить на:

  • Независимые,
  • Параметризуемые

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

Например, независимая команда Контрагенты не требует для своего выполнения какой-либо дополнительной информации. Она просто открывает список всех контрагентов.

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

Например, параметризуемая команда Расчетные счета (Объект.Поставщик) открывает список расчетных счетов некоторого конкретного контрагента. Поэтому для ее выполнения необходимо знать, расчетные счета какого именно контрагента нужно открыть. То есть контрагент является параметром этой команды.

Глобальные команды и локальные команды формы

По отношению команд к некоторой форме, все команды можно разделить на.

С помощью команды BREAK (РАЗОРВИ) объект разрывается в точке или точках, определенных пользователем. С помощью команд CHAMFER (ФАСКА) и FILLET (СОПРЯГИ ) создаются фаски и сопряжения

Зачастую бывает проще вычертить один длинный отрезок, а затем разорвать его на два и более, чем вычерчивать несколько отрезков. Команда BREAK (РАЗОРВИ) чаще всего используется при создании архитектурных планов для разрыва стен в местах дверных и оконных проемов. Если задать на объекте две точки, AutoCAD сотрет все, что находится между ними. Обычно для определения этих точек используется объектная привязка. Иногда для этого можно использовать команду TRIM (ОБРЕЖЬ), но если имеются затруднения с указанием режущих кромок, предпочтительно использовать команду BREAK (РАЗОРВИ).

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

С помощью команды CHAMFER (ФАСКА) создаются фаски на углах, образованных двумя непараллельными отрезками. Эта команда может оперировать также с прямыми, лучами и полилиниями. Угол можно создать простым удлинением отрезков до их пресечения или создать фаску. Если создается фаска, она определяется либо двумя катетами, либо одним катетом и углом фаски по отношению к одной из кромок.

Процесс создания фаски состоит из двух шагов. Сначала задаются параметры фаски. Это могут быть либо два катета, либо один катет и один угол фаски. После ввода значений AutoCAD завершит команду CHAMFER (ФАСКА). После этого нужно снова запустить эту команду и выбрать два отрезка, представляющие кромки, между которыми создается фаска. AutoCAD создаст фаску, используя полученную на предыдущем этапе информацию.

Команда FILLET (СОПРЯГИ) используется для построения плавного сопряжения двух отрезков дугой. К этой операции часто обращаются при создании чертежей механических конструкций. В некоторых случаях команда FILLET (СОПРЯГИ) может применяться вместо команды ARC (ДУГА) для создания дуг. Как и при использовании команды CHAMFER (ФАСКА), при помощи команды FILLET (СОПРЯГИ) можно сопрягать отрезки, прямые, лучи или полилинии, которые могут быть и параллельными. Но, кроме этих объектов, сопрягать можно и окружности, дуги и эллипсы. В команде для формирования сопрягающей дуги нужно задать ее радиус

Процесс сопряжения также двухшаговый. Сначала определяется радиус сопрягающей дуги. После этой операции AutoCAD завершает выполнение команды. Теперь необходимо снова начать команду FILLET (СОПРЯГИ) и выбрать два сопрягаемых отрезка. AutoCAD выполнит сопряжение отрезковы в соответствии с имеющейся информацией.

Группы .


Если у вас есть определенный набор объектов, которым целесообразно манипулировать как группой, причем вы работаете с достаточно сложным чертежом многоразового выбора, то можно бежать повторения утомительной процедуры повторного выбора, задействовав механизм объединения объектов в группу.

Создание и изменение групп. Чтобы создать или изменить группу, нужно ввести в командную строку group и открыть таким образом диалоговое окно Object Grouping (Группирование объектов).

Для создания новой группы выполните ряд операций.

1. В поле ввода Group Name (Имя группы) введите имя группы. Для имени можно использовать не более 31 символа без пробелов. В любом месте вводимого имени можно использовать дефис (-) и подчеркивание (_).

2. При желании в поле Description (Описание) можно ввести комментарий длиной не более 64 символов. В комментарий можно включать пробелы.

3. Щелкните на кнопке New (Новая). AutoCAD возвращается к чертежу и выводит в командную строку приглашение Select objects: (Выберите объект:). В ответ на это приглашение выберите объекты, которые предполагается включить в группу. Завершите выбор объектов, нажав . AutoCAD возвращает диалоговое окно на экран.

4. Щелкните на ОК .

Теперь группа сформирована для дальнейшей работы с ней.

Один объект может принадлежать нескольким группам.

В зоне Group identification (Идентификация группы) диалогового окна Object Grouping (Группировка объектов) также имеется кнопка Find Name (Найти имя). Эта кнопка используется для поиска имени группы, к которой принадлежит выбранный объект. AutoCAD позволяет выбрать объект, а затем выводит имя соответствующей группы (или групп).

Щелчок на кнопке Highlight (Подсветить) позволяет зрительно выделить заданную группу. Сначала из списка Group Name (Имя группы) выбирается группа, а после щелчка на кнопке Highlight AutoCAD возвращается к чертежу и выделяет все объекты в группе. После щелчка на кнопке Continue (Продолжить) AutoCAD возвращается в диалоговое окно. Кнопка Highlight используется в тех случаях, когда нет уверенности в правильности выбора из списка группы для дальнейшей работы.

Зона Change Group (Изменение группы) диалогового окна Object Grouping (Группирование объектов) обеспечивает гибкость управления группами. Чтобы изменить группу, нужно в списке групп Group Name в верхней части диалогового окна щелкнуть на любом имени группы. После этого все кнопки в зоне Change Group (Изменение группы) становятся доступными. Опишем их назначение.

Remove (Удалить). Если задать эту опцию, AutoCAD переключается на вывод чертежа в графическую зону экрана и выводит в командную строку приглашение Select objects to remove from group... (Выберите объект для удаления из группы...) . Выберите объекты, которые должны быть исключены из чертежа. Для завершения операции нажмите . ОК .

Add (Добавить). Если задать эту опцию, AutoCAD переключается в область чертежа и выводит в командную строку приглашение Select objects to add to group. . . (Выберите объекты для добавления в группу...). Выберите объекты, которые должны быть добавлены в группу. Для завершения операции нажмите . AutoCAD возвратится в диалоговое окно. Щелкните на ОК .

Rename (Переименовать). При задании этой опции выбирается группа, которая должна быть переименована, и в поле ввода Group Name изменяется ее имя. Щелкните на кнопке Rename (Переименуй). Имя группы в списке Group Name (Имя группы) также должно измениться. Щелкните на ОК .

Re-order (Упорядочить). Каждому объекту в группе присвоены номера, начиная с 0. В некоторых случаях имеет значение порядок размещения объектов в группе (например, при выполнении программы, оперирующей объектами группы). Выберите группу, в которой должен быть изменен порядок расположения объектов. AutoCAD откроет диалоговое окноOrder Group (Порядок группы). Если нужно расположить объекты в группе в порядке, обратном существующему, щелкните на кнопках Reverse Order (Обратный порядок). В ином случае щелкните на кнопках Highlight (Подсветить) и Previous (Предыдущий) . В правом нижнем углу этого окна

Description (Описание) . Эта опция обновляет описание группы.

Explode (Расчленить). Эта опция расчленяет группу на составляющие. Все объекты остаются на чертеже, но они перестают быть группой.

Selectable (Выбираемая). Если группа выбираема, выбор одного объекта группы означает выбор всей группы. Эта опция допускает временное переключение в режим манипуляций одиночными объектами без расчленения группы.

Технологическая платформа «1С:Предприятие 8» используется для автоматизации решения широкого круга управленческих и учетных задач на самых разных предприятиях. При такой обширной сфере применения, естественно, могут возникать ситуации, когда функциональности стандартных команд недостаточно.
Для реализации дополнительной функциональности используется встроенный язык «1С:Предприятия». В основном эта функциональность реализована в обработчиках событий. Однако возникает и необходимость предоставить пользователям возможность интерактивного обращения к части реализованных функций из интерфейса.


Для решения этих задач в «1С:Предприятии» существует возможность создавать произвольную команду. В конфигурации произвольные команды представлены новым объектом конфигурации Команда . Объект конфигурации Команда предназначен для реализации в прикладном решении нестандартных функций с возможностью использования стандартных механизмов включения реализованного функционала
в командный интерфейс.
Технологическая платформа ничем не ограничивает состав произвольных команд и реализуемые ими функции. Все определяется требованиями к конкретному прикладному решению. При создании произвольной команды разработчик должен установить ее свойства, определяющие правила включения команды в интерфейс, и написать программный код, определяющий выполняемые командой действия. Этим произвольные команды отличаются от стандартных. Для последних и свойства, и выполняемые действия определены самой платформой.
В конфигурации произвольные команды могут быть реализованы или как независимые объекты – общие команды, или как подчиненные другим объектам.

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

Произвольные общие команды

Для примера рассмотрим, как сделать и настроить все свойства команду “Настроить сканер штрих-кодов” . На торговых предприятиях часто требуется автоматизировать процесс регистрации продаваемого товара. Для этого используются сканеры штрих-кода. Однако технологическая платформа ничего «не знает» об этих устройствах и не имеет средств работы с ними. Следовательно, для работы со сканером штрих-кода требуется подключать специальную программу – драйвер. Для подключения такого драйвера реализована общая произвольная команда Установить сканер штрих-кодов. Установив определенные значения свойств этой команды, разработчик обеспечил ее доступность пользователям.

Произвольная общая команда «Настроить сканер»

Функции работы со сканером являются общими для всего прикладного решения, то есть не относятся к какому-то конкретному объекту конфигурации, поэтому произвольная команда реализована как общая.
Команда выполняет действие – подключает к прикладному решению драйвер для работы со сканером штрихкодов. Поэтому она расположена в панели действий основного окна приложения.

Еще одной распространенной задачей является получение печатных копий электронных документов. Состав документов, их структура определяются автоматизируемой прикладной задачей. Естественно, в платформе невозможно предусмотреть все многообразие документов и варианты их печатных форм. Для того чтобы «научить» документ «переносить» себя на бумагу, можно воспользоваться произвольной командой.
В демонстрационной базе для получения печатной формы документа РасходТовара создана подчиненная команда ПечатьРасходнойНакладной

Произвольная подчиненная команда «Печать расходной накладной»

Значения свойств команды Группа и Тип параметра команды определили расположение команды в командном интерфейсе – меню Печать командной панели формы документа, а процедура на встроенном языке обеспечила формирование печатной формы конкретного документа, ссылка на который передается в параметре команды.
Еще одним, достаточно специфическим вариантом использования произвольных команд является расширение или переопределение стандартной функциональности стандартной команды. Такие задачи возникают, например, вследствие требования сократить количество ручных операций или изменить стандартное поведение объектов.
Например, в нашей базе реализован объект-обработка Административный сервис . Команду открытия основной формы необходимо было расположить в панели навигации, а саму форму открывать в рабочей области основного окна приложения. Но стандартная функциональность этого объекта отличается от требуемой – команда открытия формы располагается в панели действий, а форма открывается в новом вспомогательном окне.
Для обеспечения требуемой функциональности у обработки снято свойство Использовать стандартные команды – стандартные команды нас не устраивают.

Отключение использования стандартных команд

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

Произвольная подчиненная команда «Административный сервис»

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

Размещение по умолчанию в командном интерфейсе для произвольных команд определяется:

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

ВНИМАНИЕ!
Свойство команды Группа обязательно должно быть заполнено. В противном случае возникнет ошибка при обновлении конфигурации базы данных, и обновление не выполнится.

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

  • Если команда для своего исполнения не требует параметров, то для нее выбирают группу с категорией Панель навигации или с категорией Панели действий.
  • Если команда для своего исполнения требует передачи параметра, то для нее необходимо выбрать группу с категорией Панель навигации формы или с категорией Командная панель формы.
  • Для команд, выполнение которых приводит к изменению информации, отображаемой в рабочей области того же окна, следует выбирать категорию Панель навигации для независимых команд илиПанель навигации формы для параметризуемых команд.
  • Для команд, выполнение которых приводит к изменению данных в информационной базе, следует выбирать категорию Панель действий для независимых команд или Командная панель формы для параметризуемых команд. Также эту категорию рекомендуется выбирать для команд, которые приведут к открытию нового окна для отображения форм выбора, форм отчетов, форм обработок.

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

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

Состав допустимых типов параметров для параметризуемой команды определяется ее свойством «Тип параметра команды»

Сравнивая состав типов, заданных в свойстве команды, с типами реквизитов формы, система принимает решение о включении команды в ту или иную форму.

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


  • печать ценников на все товары по всем существующим видам цен,
  • печать ценников на все товары по одному виду цен.

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

Общая независимая команда
Функционал печати всех ценников на первый взгляд должен расширять возможности справочника Товары. Однако этот объект конфигурации описывает множество объектов данных информационной базы. Если мы реализуем команду как подчиненную справочнику, то мы «научим» каждый из объектов данных печатать ценники на все товары. А это уже лишнее. Объект данных должен быть ответственен только за себя. Поэтому команда будет общей.
Для добавления произвольной общей команды используем пункт Добавить контекстного меню узла Общие команды дерева конфигурации.

Результате будет добавлена общая команда, и для нее откроется окно свойств и окно редактирования модуля команды.

Свойства и модуль общей произвольной команды

В группе свойств Основные зададим значения свойств команды:


  • Имя – «ПечатьЦенниковТовары»;
  • Синоним – оставим автоматически сформированный синоним;
  • Комментарий – заполнять не будем.

Следующий шаг – выбор категории команды и группы для ее размещения по умолчанию. Наша команда для своего исполнения не требует параметров – она независимая. Команда выполняет действия по обработке данных, хранимых в информационной базе, с целью получения набора ценников, а не изменяет контекст решения какой-либо задачи. Следовательно, для команды установим категорию Панель действий. А в какой группе она будет отображаться? Логичнее всего поместить ее в группу Сервис .
Поэтому для свойства Группа открываем окно со списком групп и выбираем элемент панель действий.Сервис .

ПРИМЕЧАНИЕ
Обратите внимание на свойства Тип параметра команды , Режим использования параметра и изменяет данные – они недоступны для заполнения. Свойства предназначены для описания параметризуемой команды и становятся доступны только при выборе группы с категориями Панель навигации формы или Командная панель формы.

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

Созданная нами команда является независимой. Следовательно, необходимо определить, в каких разделах командного интерфейса она будет доступна. Команда должна быть доступна в тех же разделах, в которых можно выполнять действия по управлению ценами.
В нашем случае созданная команда должна принадлежать трем подсистемам – Ценообразование, Цены, Предприятие. Таким образом, нам требуется отредактировать свойство Состав трех подсистем.
Для сокращения количества выполняемых действий из контекстного меню созданной команды выберем пункт Дополнительно. В результате откроется окно, в котором на закладке Подсистемы можно указать все подсистемы, которым принадлежит команда

Включение произвольной общей команды в подсистемы

Наша команда доступна пользователям с ролью Администратор за счет установленного свойства роли Устанавливать права для новых объектов. От нас требуется обеспечить ее доступность и для роли Менеджер по ценам.
Как и для других объектов конфигурации, для общей команды настройку доступности можно выполнить в окне редактирования роли.
А можно – в уже открытом окне Дополнительно на закладке Права. В списке Роли выбираем настраиваемую роль и в списке Права устанавливаем право Просмотр для созданной команды

Настройка доступности команды для роли «Менеджер по ценам»

Настройка видимости команды по ролям для произвольной независимой команды выполняется аналогично настройке для стандартных команд – в редакторе командного интерфейса.
Наша команда по умолчанию должна быть видима пользователю с ролью Менеджер по ценам, а от пользователя с ролью Администратор ее необходимо скрыть. Для этого в редакторе командного интерфейса подсистемы Ценообразование снимем флажок общей видимости в колонке Видимость . Это обеспечит нам невидимость команды для всех ролей, в том числе и вновь создаваемых. А для роли Менеджер по ценам явным образом установим флажок в соответствующей колонке.
Сохраним конфигурацию, запустим приложение от имени пользователя Менеджер по ценам и выберем раздел Управление ценами.

Настройка видимости произвольной общей команды

В командном интерфейсе команда Печать ценников товары доступна в разделе Управление ценами (за счет указания принадлежности к подсистеме Ценообразование). Команда размещена в группе Сервис панели действий (за счет указания соответствующего значения свойства Группа).

Таким образом, для произвольной общей независимой команды:

  • размещение в командном интерфейсе по умолчанию определяется значением свойства Группа;
  • включение в раздел командного интерфейса определяется принадлежностью к соответствующей подсистеме;
  • доступность для пользователя определяется значением права Просмотр.

Команду мы создали. А как рассказать пользователю о том, какие действия выполняет произвольная команда? Ответ очевиден – описать назначение команды в документации к прикладному решению. Также назначение команды можно описать во встроенной электронной справке. Для работы со справочной информацией предназначены свойства общей команды из группы Справочная информация (рис.

Справочная информация по произвольной общей команде

Однако поиск описания команды в документации или встроенной справке – процесс длительный. Можно помочь пользователю быстро вспомнить назначение команды, выбрав для нее говорящее представление. Произвольная общая команда в командном интерфейсе представляется своим свойством Синоним. Сейчас команда представлена текстом «Печать ценников товары» , и это представление достаточно информативно. Но в дальнейшем мы добавим в прикладное решение еще одну команду печати ценников – по виду цен. Поэтому стоит подумать над таким представлением команды, которое подскажет пользователю, какой вариант печати ценников будет выполнен. Скажем, это будет «Печать всех ценников» .
Еще одним способом напоминания пользователю о назначении команды является использование свойства Подсказка. Текст, заданный в этом свойстве, отображается во всплывающей подсказке при наведении указателя мыши на команду. Для свойства Подсказка зададим текст «Печать ценников на все товары по всем видам цен» . В результате изменения значений свойств Синоним и Подсказка представление команды
в командном интерфейсе изменилось.

Измененное представление команды, подсказка, справка

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