/**
   * {@inheritDoc}
   *
   * <p>Handles messages received from other clients on this channel, as well as server
   * notifications about other clients joining and leaving this channel.
   */
  public void receivedMessage(ClientChannel channel, SessionId sender, byte[] message) {
    ByteBuffer buf = ByteBuffer.wrap(message);

    byte opcode = buf.get();

    switch (opcode) {
      case OP_JOINED:
        memberList.addClient(ChatClient.getSessionId(buf));
        break;
      case OP_LEFT:
        memberList.removeClient(ChatClient.getSessionId(buf));
        break;
      case OP_MESSAGE:
        {
          byte[] contents = new byte[buf.remaining()];
          buf.get(contents);
          // The server sends us a separate, private echoback in this
          // application; those were from us originally, so use our
          // own SessionId (instead of null).
          outputArea.append(
              String.format(
                  "%s: %s\n",
                  (sender != null) ? sender : myChatClient.getSessionId(), new String(contents)));
          break;
        }
      default:
        System.err.format("Unknown opcode 0x%02X\n", opcode);
    }
  }
 /**
  * Constructs a new ChatChannelFrame as a wrapper around the given channel.
  *
  * @param client the parent {@code ChatClient} of this frame.
  * @param channel the channel that this class will manage.
  */
 public ChatChannelFrame(ChatClient client, ClientChannel channel) {
   super("Channel: " + channel.getName());
   myChatClient = client;
   myChannel = channel;
   Container c = getContentPane();
   c.setLayout(new BorderLayout());
   JPanel eastPanel = new JPanel();
   eastPanel.setLayout(new BorderLayout());
   c.add(eastPanel, BorderLayout.EAST);
   eastPanel.add(new JLabel("Users"), BorderLayout.NORTH);
   memberList = new MemberList();
   memberList.addMouseListener(myChatClient.getDCCMouseListener());
   eastPanel.add(new JScrollPane(memberList), BorderLayout.CENTER);
   JPanel southPanel = new JPanel();
   c.add(southPanel, BorderLayout.SOUTH);
   southPanel.setLayout(new GridLayout(1, 0));
   inputField = new JTextField();
   southPanel.add(inputField);
   outputArea = new JTextArea();
   c.add(new JScrollPane(outputArea), BorderLayout.CENTER);
   inputField.addActionListener(this);
   setSize(400, 400);
   setClosable(true);
   setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
   addInternalFrameListener(new FrameClosingListener(this));
   setResizable(true);
   setVisible(true);
 }