Как обновить информацию xdata объекта при его копировании - PullRequest
0 голосов
/ 01 июля 2019

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

Проблема возникает, когда я копирую строку с текстами, где каждый получает новый дескриптор, но сохраненные xdata дают старые дескрипторы, что приводит к дальнейшим проблемам. Я думал, что реактор vlr-copied может решить мою проблему, но так как я не очень опытен с реакторами, я не могу заставить его работать.

Может ли кто-нибудь указать мне правильное направление? Я нашел это

http://www.theswamp.org/index.php?topic=42654.0

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

Любое предложение приветствуется. Спасибо.

1 Ответ

1 голос
/ 01 июля 2019

Во-первых, вам нужно определиться с поведением, которое вы хотите, чтобы объекты демонстрировали, предполагая, что один объект (текст или строка) копируется независимо от другого. Поскольку эти два объекта связаны, вам может потребоваться решить, какой объект является 'master' , а какой 'slave * .

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

Это подход, которым я руководствовался при разработке своего приложения Associative Textbox (которое по сути решает одну и ту же задачу - связать два объекта на чертеже - в моем случае, текстовый объект и ограничивающую рамку) .

В моем приложении я использую отдельный Object Reactor для обработки событий модификации для текстового объекта и текстового поля соответственно:

(vlr-object-reactor txt "tbox-textreactor"
   '(
        (:vlr-modified . tbox:textcallback)
        (:vlr-copied   . tbox:textcopied)
    )
)
(vlr-object-reactor box "tbox-tboxreactor"
   '(
        (:vlr-modified . tbox:tboxcallback)
        (:vlr-copied   . tbox:tboxcopied)
    )
)

Как и ваши настройки, они создаются и настраиваются при загрузке программы с использованием расширенных данных объекта (xData), прикрепленных как к тексту, так и к текстовому полю.

Когда вызывается событие Copy для texbox (оценивается функция обратного вызова tbox:tboxcopied), я решаю, что текстовое поле не может жить без текста, который в нем содержится, и поэтому я удаляю потерянное текстовое поле из чертежа.

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

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

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

(defun tbox:tboxcopied ( owner reactor params )
    (if (/= 0 (car params))
        (progn
            (setq tbox:owner (append tbox:owner (list (car params))))
            (vlr-command-reactor "tbox-tboxcopiedcommreactor"
               '(
                    (:vlr-commandended     . tbox:tboxcopiedcommandended)
                    (:vlr-commandcancelled . tbox:tboxcopiedcommandcancelled)
                    (:vlr-commandfailed    . tbox:tboxcopiedcommandcancelled)
                )
            )            
        )
    )
    (princ)
)

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

(defun tbox:tboxcopiedcommandended ( reactor params / ent )
    (vlr-remove reactor) ;; <----- Remove temporary Command Reactor
    (if
        (and
            (setq ent (car tbox:owner))
            (member (cdr (assoc 0 (entget ent))) '("CIRCLE" "LWPOLYLINE"))
        )
        (entdel ent) ;; <----- Delete orphan textbox
    )
    (setq tbox:owner (cdr tbox:owner))
    (princ)
)

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

(defun tbox:textcopied ( owner reactor params )
    (if (/= 0 (car params))
        (progn
            (setq tbox:owner (append tbox:owner (list (car params))))
            (vlr-command-reactor "tbox-textcopiedcommreactor"
               '(
                    (:vlr-commandended     . tbox:textcopiedcommandended)
                    (:vlr-commandcancelled . tbox:textcopiedcommandcancelled)
                    (:vlr-commandfailed    . tbox:textcopiedcommandcancelled)
                )
            )
        )
    )
    (princ)
)

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

(defun tbox:textcopiedcommandended ( reactor params / box ent enx val )
    (vlr-remove reactor) ;; <----- Remove temporary Command Reactor
    (if
        (and
            (setq ent (car tbox:owner))
            (setq enx (entget ent (list tbox:app)))
            (member (cdr (assoc 0 enx)) '("TEXT" "MTEXT"))
            (setq val (cdadr (assoc -3 enx)))
            (setq box (tbox:createbox enx (cdr (assoc 1000 val)) (cdr (assoc 1040 val))))
        )
        (progn
            (entmod
                (append (vl-remove (assoc 40 enx) (entget ent))
                    (list
                        (list -3
                            (list tbox:app
                               '(1002 . "{")
                                (cons  1005 (cdr (assoc 5 (entget box))))
                                (assoc 1000 val)
                                (assoc 1040 val)
                               '(1002 . "}")
                            )
                        )
                    )
                )
            )
            (if (= 'vlr-object-reactor (type tbox:textreactor))
                (vlr-owner-add tbox:textreactor (vlax-ename->vla-object ent))
            )
            (if (= 'vlr-object-reactor (type tbox:tboxreactor))
                (vlr-owner-add tbox:tboxreactor (vlax-ename->vla-object box))
            )                    
        )            
    )
    (setq tbox:owner (cdr tbox:owner))
    (princ)
)

И методы, которые я описал выше, я бы рекомендовал для вашего сценария:

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

...