Интеллектуальные ручки пользовательского объекта в MultiCAD.NET

9ff1733ca4f24261b894cef7a8f7ddd1.pngУдобство редактирования чертежей является одной из ключевых характеристик систем автоматизированного проектирования. Важным инструментом для работы с объектами чертежа служат ручки (grips) — специальные маркеры в ключевых точках объекта, которые позволяют видоизменять объект с помощью мыши, без использования меню или командной строки.

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

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

Класс McSmartGripДля описания интеллектуальных ручек в MultiCAD.NET API используется класс McSmartGrip. Данный класс содержит несколько вариантов конструктора с различными списками параметров, а также обработчики событий, которые генерируются в зависимости от действий пользователя: MoveGrip — вызывается при перемещении ручки, MouseMove — вызывается при перемещении ручки интерактивного типа, GetContextMenu — вызывается при щелчке на ручке с типом GripType.PopupMenu, OnCommand — вызывается при щелчке на ручке с типом GripType.Button или по пункту контекстного меню полученного из GetContextMenu. Например, для создания простой ручки, отвечающей за перемещение точки объекта, может быть использован следующий конструктор: var simpleGrip = new McSmartGrip(position, (obj, g, offset) => { obj.TryModify (); obj._pnt += offset; } Данный конструктор предусматривает реализацию делегата MoveGrip, что мы и сделали, с помощью лямбда-выражения (http://msdn.microsoft.com/ru-ru/library/bb397687.aspx), а именно, переместили позицию объекта на величину offset.Регистрация ручек Регистрация ручек пользовательского объекта производится с помощью метода AppendGrip () класса GripPointsInfo: public void AppendGrip (Multicad.CustomObjectBase.McBaseGrip grip); Этот класс используется в качестве аргумента метода GetGripPoints (), который вызывается для получения ручек каждый раз при отображении объекта: public virtual bool GetGripPoints (Multicad.CustomObjectBase.GripPointsInfo info); Следующий фрагмент кода создает и добавляет всю ту же простую ручку: public override bool GetGripPoints (GripPointsInfo info) { info.AppendGrip (new McSmartGrip(_pnt, (obj, g, offset) => { obj.TryModify (); obj._pnt += offset; })); } Как видите, вся процедура очень компактна и занимает всего одну строку кода. Однако, это касалось самого элементарного случая, а именно, простых ручек. Давайте рассмотрим какие еще типы ручек поддерживаются в MultiCAD.NET API, а также специфику работы с каждым из них.Типы ручек Используя MulitiCAD.NET, можно создавать ручки следующих типов: Simple — простая ручка. Обработка перемещения ручки, реализуется в MoveGrip. PopupMenu — ручка, по щелчку на которой отображается всплывающие меню. Обработка события реализуется в OnCommand. Button — ручка-кнопка, при нажатии на которую выполняются действия, описанные в OnCommand. Interactive — тип, похожий на Simple, но позволяющий работать с объектными привязками. В отличие от простой ручки обработка события реализуется в MouseMove. Внешний вид ручек Один объект может содержать несколько ручек различного типа; для того, чтобы визуально их различать, можно назначить внешний вид каждой из них, определив ее форму и цвет. Многообразие форм ручек определяется перечислением McBaseGrip.GripAppearance. Вот некоторые из них: d86b39bdbc6b4b08bb6d77e126049d03.png

Также может быть задан желаемый цвет ручек из набора цветов, определенного в классе GripColors, или же можно определить цвет стандартным способом, с помощью System.Drawing.Color.Давайте посмотрим как это работает. В качестве примера возьмем знакомый нам примитив TextInBox, описанный в этой статье и создадим для него несколько интеллектуальных ручек различного типа.

Простая ручка Этот вид ручек мы уже упоминали в статье, и, как можно догадаться из названия, он используется для простых действий, например, для перемещения точек объекта. Добавим одну простую ручку для перемещения угловой точки нашего примитива: info.AppendGrip (new McSmartGrip(_pnt, (obj, g, offset) => { obj.TryModify (); obj._pnt += offset; })); Результат работы такой ручки — на анимированной иллюстрации: 61d147972563497fb457aa3d1c58c646.gif

Ручка-кнопка Добавим ручку-кнопку, которая будет управлять отображением рамки вокруг текста по нажатию. Для создания такой ручки используется конструктор с указанием типа ручки McBaseGrip.GripType.Button и базовым цветом. Обработчик нажатия на кнопку OnCommand меняет значение индикатор рисования рамки _show_frame на обратное. Для созданной ручки-кнопки определим внешний вид «включено», который будет меняться на «выключено» при нажатии, и обратно. var OnOffGrip = new McSmartGrip(McBaseGrip.GripType.Button, 1, _pnt + stepVector, McBaseGrip.GripAppearance.SwitchOn, 0, «Hide Frame», GripColors.Base); OnOffGrip.Tag = «OnOffGrip»; if (_show_frame == false) OnOffGrip.SetAppearanceAndText (McBaseGrip.GripAppearance.SwitchOff, «Show frame»); OnOffGrip.OnCommand = (obj, commandId, grip) => { obj.TryModify (); obj._show_frame = ! obj._show_frame;}; info.AppendGrip (OnOffGrip); Результат:

2151db4535c749c58a701f893a357ea7.gif

Также по нажатию ручки-кнопки может быть вызвана необходимая зарегистрированная команда:

var cmdGrip = new McSmartGrip(McBaseGrip.GripType.Button, 1, _pnt + 2 * stepVector, McBaseGrip.GripAppearance.Circle, 0, «button», GripColors.Base); cmdGrip.Tag=«cmd»; cmdGrip.OnCommand = (obj, commandId, grip) => { McContext.ExecuteCommand (grip.Tag.ToString ()); }; Ручка-меню Еще один тип ручек, который можно создавать в MultiCAD.NET — ручка для вызова контекстного меню. Данный вид ручек используется, когда пользователю необходимо выбрать из списка необходимое значение параметра объекта из списка.Данный вид ручек создается с помощью конструктора с указанием типа McBaseGrip.GripType.PopupMenu и внешнего вида, определенного значением McBaseGrip.GripAppearance.PopupMenu. Для работы с контекстным меню необходимо реализовать два делегата: GetContextMenu — вызов меню при нажатии на ручку, OnCommand — вызов действий при выборе пунктов var ctxGrip = new McSmartGrip(McBaseGrip.GripType.PopupMenu, 2, _pnt + 2 * stepVector, McBaseGrip.GripAppearance.PopupMenu, 0, «Select menu», System.Drawing.Color.Lime); ctxGrip.GetContextMenu = (obj, items) => { items.Add (new ContextMenuItem («Command 1», «none», 1)); }; ctxGrip.OnCommand = (obj, commandId, grip) => { if (grip.Id == 2) { switch (commandId) { case 1: { MessageBox.Show («Command 1 is selected»); break; } } } }; info.AppendGrip (ctxGrip); Результат:

7bc58ff30a7142d180579582f4be7562.gif

Интерактивная ручка И, наконец, последний тип ручек, который мы рассмотрим — интерактивный. Главное отличие этих ручек в том, что они могут использовать информацию об объектах привязки и в зависимости от этого определять свое поведение.В качестве примера, добавим одну из таких ручек, которая позволит менять текст нашего примитива на имя выбранного объекта (за исключением родительского объекта). В зависимости от объекта привязки ручка будет менять цвет: в исходном состоянии ручка будет иметь цвет GripColors.Base, при наведении на родительский объект цвет будет меняться на Color.Red, на любой другой объект, поддерживающий привязку — на Color.Green.Интерактивная ручка создается конструктором с указанием типа McBaseGrip.GripType.Interactive, а работа ручки реализуется в делегате MouseMove (в отличие от простых ручек, где используется MoveGrip). var interactiveGrip = new McSmartGrip(McBaseGrip.GripType.Interactive, 3, _pnt + 3 * stepVector, McBaseGrip.GripAppearance.Arrow, 0, «interactive», GripColors.Base); interactiveGrip.IsMovable = true; interactiveGrip.MouseMove = (obj, entInfo, grip, offset) => { grip.Color = GripColors.Base; if (! entInfo.SnapedObjectId.IsNull) { if (ID == entInfo.SnapedObjectId) { grip.Color = Color.Red; } else { grip.Color = Color.Green; obj.TryModify (); obj.Text = (entInfo.SnapedObjectId.GetObject ().GetType ().ToString ()); } } }; info.AppendGrip (interactiveGrip); Результат: текст «Text field» заменен на «MultiCAD.Samples.TextInBox».2ba62b7783f6428084e88d4f37610041.gif

Мы перечислили основные типы интеллектуальных ручек, которые позволяют создать эффективный интерфейс для работы с пользовательскими объектами, созданными на MultiCAD.NET. Документация по MultiCAD.NET входит в состав nanoCAD SDK, доступ к которому можно получить, зарегистрировавшись в Клубе разработчиков nanoCAD.

© Habrahabr.ru