Repository: Qiskit/qiskit

Issue:
Displaying control-annotated operations 
### Environment

- **Qiskit Terra version**: development
- **Python version**: 3.10
- **Operating system**: windows


### What is happening?

#11202 added drawer support to annotated operations.

However, for a gate with 2 or more qubits, its controlled-annotated version is not displayed correctly: the box for the controlled gate does not include all of its qubits. The code snippet in the next session draws a control-annotated CX-gate with 1 control qubit, leading to:

```
q_0: ──■───
     ┌─┴──┐
q_1: ┤ Cx ├
     └────┘
q_2: ──────           
```
The box for the CX-gate should include both `q_1` and `q_2`.


### How can we reproduce the issue?

```
from qiskit.circuit import QuantumCircuit
from qiskit.circuit.annotated_operation import AnnotatedOperation, InverseModifier, ControlModifier
from qiskit.circuit.library import CXGate

gate = AnnotatedOperation(CXGate(), ControlModifier(1))
circuit = QuantumCircuit(gate.num_qubits)
circuit.append(gate, range(gate.num_qubits))
print(circuit)
```

### What should happen?

As explained above, the box for the controlled gate should include all of its qubits (namely, `q_1` and `q_2`).

### Any suggestions?

_No response_


Discussion:

Resolving patch:
diff --git a/qiskit/visualization/circuit/text.py b/qiskit/visualization/circuit/text.py
--- a/qiskit/visualization/circuit/text.py
+++ b/qiskit/visualization/circuit/text.py
@@ -1189,7 +1189,22 @@ def add_connected_gate(node, gates, layer, current_cons, gate_wire_map):
             )
             gates, controlled_top, controlled_bot, controlled_edge, rest = controls_array
             if mod_control:
-                gates.append(BoxOnQuWire(gate_text, conditional=conditional))
+                if len(rest) == 1:
+                    gates.append(BoxOnQuWire(gate_text, conditional=conditional))
+                else:
+                    top_connect = "┴" if controlled_top else None
+                    bot_connect = "┬" if controlled_bot else None
+                    indexes = layer.set_qu_multibox(
+                        rest,
+                        gate_text,
+                        conditional=conditional,
+                        controlled_edge=controlled_edge,
+                        top_connect=top_connect,
+                        bot_connect=bot_connect,
+                    )
+                    for index in range(min(indexes), max(indexes) + 1):
+                        # Dummy element to connect the multibox with the bullets
+                        current_cons.append((index, DrawElement("")))
             elif base_gate.name == "z":
                 # cz
                 gates.append(Bullet(conditional=conditional))


Test patch:
diff --git a/test/python/visualization/test_circuit_text_drawer.py b/test/python/visualization/test_circuit_text_drawer.py
--- a/test/python/visualization/test_circuit_text_drawer.py
+++ b/test/python/visualization/test_circuit_text_drawer.py
@@ -45,6 +45,7 @@
     U3Gate,
     XGate,
     CZGate,
+    CXGate,
     ZGate,
     YGate,
     SGate,
@@ -6347,6 +6348,29 @@ def test_annotated_operation(self):
             expected,
         )
 
+    def test_annotated_multi_qubit(self):
+        """Test AnnotatedOperation and other non-Instructions."""
+        expected = "\n".join(
+            [
+                "                  ",
+                "q_0: ──────o──────",
+                "     ┌─────┴─────┐",
+                "q_1: ┤0          ├",
+                "     │  Cx - Inv │",
+                "q_2: ┤1          ├",
+                "     └─────┬─────┘",
+                "q_3: ──────■──────",
+                "                  ",
+            ]
+        )
+        gate = AnnotatedOperation(CXGate(), [ControlModifier(2, 2), InverseModifier()])
+        circuit = QuantumCircuit(gate.num_qubits)
+        circuit.append(gate, [0, 3, 1, 2])
+        self.assertEqual(
+            str(circuit_drawer(circuit, output="text", initial_state=False)),
+            expected,
+        )
+
 
 if __name__ == "__main__":
     unittest.main()