Example #1
0
void SkeinWindow::OnContextMenu(CWnd* pWnd, CPoint point)
{
  // No menu if currently editing
  if (m_edit.IsWindowVisible())
    return;

  // No menu if running the game
  bool gameRunning = GetParentFrame()->SendMessage(WM_GAMERUNNING) != 0;
  bool gameWaiting = GetParentFrame()->SendMessage(WM_GAMEWAITING) != 0;
  if (gameRunning && !gameWaiting)
    return;

  // Find the node under the mouse, if any
  CPoint cp(point);
  ScreenToClient(&cp);
  Skein::Node* node = NodeAtPoint(cp);
  if (node == NULL)
    return;

  // Get the context menu
  CMenu popup;
  popup.LoadMenu(IDR_SKEIN);
  CMenu* menu = popup.GetSubMenu(0);

  // Update the state of the context menu items
  if (node->GetParent() == NULL)
  {
    menu->RemoveMenu(ID_SKEIN_EDIT,MF_BYCOMMAND);
    menu->RemoveMenu(ID_SKEIN_ADD_LABEL,MF_BYCOMMAND);
    menu->RemoveMenu(ID_SKEIN_EDIT_LABEL,MF_BYCOMMAND);
    menu->RemoveMenu(ID_SKEIN_INSERT_KNOT,MF_BYCOMMAND);
    menu->RemoveMenu(ID_SKEIN_DELETE,MF_BYCOMMAND);
    menu->RemoveMenu(ID_SKEIN_DELETE_BELOW,MF_BYCOMMAND);
    menu->RemoveMenu(ID_SKEIN_DELETE_THREAD,MF_BYCOMMAND);
    menu->RemoveMenu(ID_SKEIN_LOCK,MF_BYCOMMAND|MF_GRAYED);
    menu->RemoveMenu(ID_SKEIN_UNLOCK,MF_BYCOMMAND|MF_GRAYED);
    menu->RemoveMenu(ID_SKEIN_LOCK_THREAD,MF_BYCOMMAND|MF_GRAYED);
    menu->RemoveMenu(ID_SKEIN_UNLOCK_THREAD,MF_BYCOMMAND|MF_GRAYED);
  }
  else
  {
    if (gameRunning && m_skein->InCurrentThread(node))
    {
      menu->EnableMenuItem(ID_SKEIN_DELETE,MF_BYCOMMAND|MF_GRAYED);
      menu->EnableMenuItem(ID_SKEIN_DELETE_BELOW,MF_BYCOMMAND|MF_GRAYED);
    }
    if (gameRunning && m_skein->InCurrentThread(m_skein->GetThreadTop(node)))
      menu->EnableMenuItem(ID_SKEIN_DELETE_THREAD,MF_BYCOMMAND|MF_GRAYED);
    if (node->GetLabel().IsEmpty())
      menu->RemoveMenu(ID_SKEIN_EDIT_LABEL,MF_BYCOMMAND);
    else
      menu->RemoveMenu(ID_SKEIN_ADD_LABEL,MF_BYCOMMAND);
  }
  if (node->GetTemporary())
  {
    menu->RemoveMenu(ID_SKEIN_UNLOCK,MF_BYCOMMAND|MF_GRAYED);
    menu->RemoveMenu(ID_SKEIN_UNLOCK_THREAD,MF_BYCOMMAND|MF_GRAYED);
  }
  else
  {
    menu->RemoveMenu(ID_SKEIN_LOCK,MF_BYCOMMAND|MF_GRAYED);
    menu->RemoveMenu(ID_SKEIN_LOCK_THREAD,MF_BYCOMMAND|MF_GRAYED);
  }

  // Show the context menu
  int cmd = menu->TrackPopupMenuEx(TPM_LEFTALIGN|TPM_TOPALIGN|TPM_NONOTIFY|TPM_RETURNCMD,
    point.x,point.y,GetParentFrame(),NULL);

  // Act on the context menu choice
  switch (cmd)
  {
  case ID_SKEIN_PLAY:
    GetParentFrame()->SendMessage(WM_PLAYSKEIN,(WPARAM)node);
    break;
  case ID_SKEIN_EDIT:
    StartEdit(node,false);
    break;
  case ID_SKEIN_ADD_LABEL:
  case ID_SKEIN_EDIT_LABEL:
    // Make sure that the label background is visible
    Invalidate();
    StartEdit(node,true);
    break;
  case ID_SKEIN_TRANSCRIPT:
    GetParentFrame()->SendMessage(WM_SHOWTRANSCRIPT,(WPARAM)node,(LPARAM)GetSafeHwnd());
    break;
  case ID_SKEIN_LOCK:
    m_skein->Lock(node);
    break;
  case ID_SKEIN_UNLOCK:
    m_skein->Unlock(node);
    break;
  case ID_SKEIN_LOCK_THREAD:
    m_skein->Lock(m_skein->GetThreadBottom(node));
    break;
  case ID_SKEIN_UNLOCK_THREAD:
    m_skein->Unlock(m_skein->GetThreadTop(node));
    break;
  case ID_SKEIN_NEW_THREAD:
    {
      Skein::Node* newNode = m_skein->AddNew(node);

      // Force a repaint so that the new node is drawn and recorded
      Invalidate();
      UpdateWindow();
      StartEdit(newNode,false);
    }
    break;
  case ID_SKEIN_INSERT_KNOT:
    {
      Skein::Node* newNode = m_skein->AddNewParent(node);
      Invalidate();
      UpdateWindow();
      StartEdit(newNode,false);
    }
    break;
  case ID_SKEIN_DELETE:
    if (CanRemove(node))
      m_skein->RemoveSingle(node);
    break;
  case ID_SKEIN_DELETE_BELOW:
    if (CanRemove(node))
      m_skein->RemoveAll(node);
    break;
  case ID_SKEIN_DELETE_THREAD:
    {
      Skein::Node* topNode = m_skein->GetThreadTop(node);
      if (CanRemove(topNode))
        m_skein->RemoveAll(topNode);
    }
    break;
  case ID_SKEIN_SAVE_TRANSCRIPT:
    {
      SimpleFileDialog dialog(FALSE,"txt",NULL,OFN_HIDEREADONLY|OFN_ENABLESIZING,
        "Text Files (*.txt)|*.txt|All Files (*.*)|*.*||",this);
      dialog.m_ofn.lpstrTitle = "Save the transcript up to this knot";
      if (dialog.DoModal() == IDOK)
        m_skein->SaveTranscript(node,dialog.GetPathName());
    }
    break;
  case 0:
    // Make sure this window still has the focus
    SetFocus();
    break;
  }
}