|
4 | 4 | CommandExecutionContext, |
5 | 5 | CommandReturn, |
6 | 6 | ISnapper, |
| 7 | + isSelected, |
| 8 | + SChildElementImpl, |
7 | 9 | SModelElementImpl, |
8 | 10 | SNodeImpl, |
9 | 11 | SParentElementImpl, |
@@ -314,3 +316,171 @@ export class DeleteLabelTypeCommand extends Command { |
314 | 316 | return this.execute(context); |
315 | 317 | } |
316 | 318 | } |
| 319 | + |
| 320 | +interface LabelToAllOrSelectionAction extends Action { |
| 321 | + labelAssignment: LabelAssignment; |
| 322 | +} |
| 323 | + |
| 324 | +abstract class LabelToAllOrSelectionCommand extends Command { |
| 325 | + @inject(EditorModeController) |
| 326 | + @optional() |
| 327 | + protected readonly editorModeController?: EditorModeController; |
| 328 | + |
| 329 | + protected elements?: SModelElementImpl[]; |
| 330 | + |
| 331 | + constructor( |
| 332 | + @inject(TYPES.Action) protected action: LabelToAllOrSelectionAction, |
| 333 | + @inject(TYPES.ISnapper) protected snapper: ISnapper, |
| 334 | + ) { |
| 335 | + super(); |
| 336 | + } |
| 337 | + |
| 338 | + protected fetchElements(context: CommandExecutionContext): SModelElementImpl[] { |
| 339 | + if (this.editorModeController?.isReadOnly()) { |
| 340 | + return []; |
| 341 | + } |
| 342 | + |
| 343 | + const allElements = getAllElements(context.root.children); |
| 344 | + const selectedElements = allElements.filter((element) => isSelected(element)); |
| 345 | + return selectedElements.length === 0 ? allElements : selectedElements; |
| 346 | + } |
| 347 | + |
| 348 | + protected addLabel(context: CommandExecutionContext) { |
| 349 | + if (this.editorModeController?.isReadOnly()) { |
| 350 | + return context.root; |
| 351 | + } |
| 352 | + |
| 353 | + if (this.elements === undefined) { |
| 354 | + this.elements = this.fetchElements(context); |
| 355 | + } |
| 356 | + |
| 357 | + this.elements.forEach((element) => { |
| 358 | + if (containsDfdLabels(element)) { |
| 359 | + const hasBeenAdded = |
| 360 | + element.labels.find((as) => { |
| 361 | + return ( |
| 362 | + as.labelTypeId === this.action.labelAssignment.labelTypeId && |
| 363 | + as.labelTypeValueId === this.action.labelAssignment.labelTypeValueId |
| 364 | + ); |
| 365 | + }) !== undefined; |
| 366 | + if (!hasBeenAdded) { |
| 367 | + element.labels.push(this.action.labelAssignment); |
| 368 | + if (element instanceof SNodeImpl) { |
| 369 | + snapPortsOfNode(element, this.snapper); |
| 370 | + } |
| 371 | + } |
| 372 | + } |
| 373 | + }); |
| 374 | + |
| 375 | + return context.root; |
| 376 | + } |
| 377 | + |
| 378 | + protected removeLabel(context: CommandExecutionContext) { |
| 379 | + if (this.editorModeController?.isReadOnly()) { |
| 380 | + return context.root; |
| 381 | + } |
| 382 | + |
| 383 | + if (this.elements === undefined) { |
| 384 | + this.elements = this.fetchElements(context); |
| 385 | + } |
| 386 | + |
| 387 | + this.elements.forEach((element) => { |
| 388 | + if (containsDfdLabels(element)) { |
| 389 | + const labels = element.labels; |
| 390 | + const idx = labels.findIndex( |
| 391 | + (l) => |
| 392 | + l.labelTypeId == this.action.labelAssignment.labelTypeId && |
| 393 | + l.labelTypeValueId == this.action.labelAssignment.labelTypeValueId, |
| 394 | + ); |
| 395 | + if (idx >= 0) { |
| 396 | + labels.splice(idx, 1); |
| 397 | + if (element instanceof SNodeImpl) { |
| 398 | + snapPortsOfNode(element, this.snapper); |
| 399 | + } |
| 400 | + } |
| 401 | + } |
| 402 | + }); |
| 403 | + |
| 404 | + return context.root; |
| 405 | + } |
| 406 | +} |
| 407 | + |
| 408 | +export interface AddLabelToAllOrSelectionAction extends LabelToAllOrSelectionAction { |
| 409 | + kind: typeof AddLabelToAllOrSelectionAction.TYPE; |
| 410 | +} |
| 411 | +export namespace AddLabelToAllOrSelectionAction { |
| 412 | + export const TYPE = "add-label-to-all-or-selection"; |
| 413 | + export function create(labelAssignment: LabelAssignment): AddLabelToAllOrSelectionAction { |
| 414 | + return { |
| 415 | + kind: TYPE, |
| 416 | + labelAssignment, |
| 417 | + }; |
| 418 | + } |
| 419 | +} |
| 420 | +@injectable() |
| 421 | +export class AddLabelToAllOrSelectionCommand extends LabelToAllOrSelectionCommand { |
| 422 | + public static readonly KIND = AddLabelToAllOrSelectionAction.TYPE; |
| 423 | + |
| 424 | + constructor(@inject(TYPES.Action) action: AddLabelAssignmentAction, @inject(TYPES.ISnapper) snapper: ISnapper) { |
| 425 | + super(action, snapper); |
| 426 | + } |
| 427 | + |
| 428 | + execute(context: CommandExecutionContext): CommandReturn { |
| 429 | + return this.addLabel(context); |
| 430 | + } |
| 431 | + |
| 432 | + undo(context: CommandExecutionContext): CommandReturn { |
| 433 | + return this.removeLabel(context); |
| 434 | + } |
| 435 | + |
| 436 | + redo(context: CommandExecutionContext): CommandReturn { |
| 437 | + return this.execute(context); |
| 438 | + } |
| 439 | +} |
| 440 | + |
| 441 | +export interface DeleteLabelFromAllOrSelectionAction extends LabelToAllOrSelectionAction { |
| 442 | + kind: typeof DeleteLabelFromAllOrSelectionAction.TYPE; |
| 443 | +} |
| 444 | +export namespace DeleteLabelFromAllOrSelectionAction { |
| 445 | + export const TYPE = "delete-label-from-all-or-selection"; |
| 446 | + export function create(labelAssignment: LabelAssignment): DeleteLabelFromAllOrSelectionAction { |
| 447 | + return { |
| 448 | + kind: TYPE, |
| 449 | + labelAssignment, |
| 450 | + }; |
| 451 | + } |
| 452 | +} |
| 453 | +@injectable() |
| 454 | +export class DeleteLabelFromAllOrSelectionCommand extends LabelToAllOrSelectionCommand { |
| 455 | + public static readonly KIND = DeleteLabelFromAllOrSelectionAction.TYPE; |
| 456 | + |
| 457 | + constructor( |
| 458 | + @inject(TYPES.Action) action: DeleteLabelFromAllOrSelectionAction, |
| 459 | + @inject(TYPES.ISnapper) snapper: ISnapper, |
| 460 | + ) { |
| 461 | + super(action, snapper); |
| 462 | + } |
| 463 | + |
| 464 | + execute(context: CommandExecutionContext): CommandReturn { |
| 465 | + return this.removeLabel(context); |
| 466 | + } |
| 467 | + |
| 468 | + undo(context: CommandExecutionContext): CommandReturn { |
| 469 | + return this.addLabel(context); |
| 470 | + } |
| 471 | + |
| 472 | + redo(context: CommandExecutionContext): CommandReturn { |
| 473 | + return this.execute(context); |
| 474 | + } |
| 475 | +} |
| 476 | + |
| 477 | +function getAllElements(elements: readonly SChildElementImpl[]): SModelElementImpl[] { |
| 478 | + const elementsList: SModelElementImpl[] = []; |
| 479 | + for (const element of elements) { |
| 480 | + elementsList.push(element); |
| 481 | + if ("children" in element) { |
| 482 | + elementsList.push(...getAllElements(element.children)); |
| 483 | + } |
| 484 | + } |
| 485 | + return elementsList; |
| 486 | +} |
0 commit comments