📄 treewin.cc
字号:
//// $Source: /home/gambit/CVS/gambit/sources/gui/treewin.cc,v $// $Date: 2002/09/14 23:24:42 $// $Revision: 1.34.2.1 $//// DESCRIPTION:// Implementation of window class to display extensive form tree//// This file is part of Gambit// Copyright (c) 2002, The Gambit Project//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//#include "wx/wxprec.h"#ifndef WX_PRECOMP#include "wx/wx.h"#endif // WX_PRECOMP#include "wx/dcps.h"#include "wx/dragimag.h"#include "base/gmisc.h"#include "math/gmath.h"#include "game/efg.h"#include "treewin.h"#include "efgshow.h"#include "game/efgutils.h"#include "base/glist.imp"//----------------------------------------------------------------------// TreeWindow: Member functions//----------------------------------------------------------------------BEGIN_EVENT_TABLE(TreeWindow, wxScrolledWindow) EVT_SIZE(TreeWindow::OnSize) EVT_MOTION(TreeWindow::OnMouseMotion) EVT_LEFT_DOWN(TreeWindow::OnLeftClick) EVT_LEFT_DCLICK(TreeWindow::OnLeftDoubleClick) EVT_LEFT_UP(TreeWindow::OnMouseMotion) EVT_RIGHT_DOWN(TreeWindow::OnRightClick) EVT_CHAR(TreeWindow::OnKeyEvent)END_EVENT_TABLE()//----------------------------------------------------------------------// TreeWindow: Constructor and destructor//----------------------------------------------------------------------TreeWindow::TreeWindow(EfgShow *p_efgShow, wxWindow *p_parent) : wxScrolledWindow(p_parent), m_efg(*p_efgShow->Game()), m_parent(p_efgShow), m_layout(m_efg, this), m_zoom(1.0), m_dragImage(0), m_dragSource(0){ // Make sure that Chance player has a name m_efg.GetChance()->SetName("Chance"); SetBackgroundColour(*wxWHITE); MakeMenus();}TreeWindow::~TreeWindow(){ }void TreeWindow::MakeMenus(void){ m_nodeMenu = new wxMenu; m_nodeMenu->Append(wxID_CUT, "Cut subtree", "Cut subtree to clipboard"); m_nodeMenu->Append(wxID_COPY, "Copy subtree", "Copy subtree to clipboard"); m_nodeMenu->Append(wxID_PASTE, "Paste subtree", "Paste subtree from clipboard"); m_nodeMenu->AppendSeparator(); m_nodeMenu->Append(efgmenuEDIT_INSERT, "Insert move", "Insert a move"); m_nodeMenu->Append(efgmenuEDIT_REVEAL, "Reveal move", "Reveal this move"); m_nodeMenu->AppendSeparator(); m_nodeMenu->Append(efgmenuEDIT_TOGGLE_SUBGAME, "Mark subgame", "Mark or unmark this subgame"); m_nodeMenu->Append(efgmenuEDIT_MARK_SUBGAME_TREE, "Mark subgame tree", "Mark all subgames in this tree"); m_nodeMenu->Append(efgmenuEDIT_UNMARK_SUBGAME_TREE, "Unmark subgame tree", "Unmark all subgames in this tree"); m_nodeMenu->AppendSeparator(); m_nodeMenu->Append(efgmenuEDIT_NODE, "Edit node", "View and change node properties"); m_nodeMenu->Append(efgmenuEDIT_MOVE, "Edit move", "View and change move properties"); m_nodeMenu->Append(efgmenuEDIT_GAME, "Edit game", "View and change game properties"); m_gameMenu = new wxMenu; m_gameMenu->Append(efgmenuEDIT_GAME, "Edit game", "View and change game properties");}//---------------------------------------------------------------------// TreeWindow: Event-hook members//---------------------------------------------------------------------static Node *PriorSameIset(const Node *n){ Infoset *iset = n->GetInfoset(); if (!iset) return 0; for (int i = 1; i <= iset->NumMembers(); i++) if (iset->Members()[i] == n) if (i > 1) return iset->Members()[i-1]; else return 0; return 0;}static Node *NextSameIset(const Node *n){ Infoset *iset = n->GetInfoset(); if (!iset) return 0; for (int i = 1; i <= iset->NumMembers(); i++) if (iset->Members()[i] == n) if (i < iset->NumMembers()) return iset->Members()[i+1]; else return 0; return 0;}//// OnKeyEvent -- handle keypress events// Currently we support the following keys:// left arrow: go to parent of current node// right arrow: go to first child of current node// up arrow: go to previous sibling of current node// down arrow: go to next sibling of current node// Since the addition of collapsible subgames, a node's parent may not// be visible in the current display. Thus, find the first predecessor// that is visible (ROOT is always visible)//void TreeWindow::OnKeyEvent(wxKeyEvent &p_event){ if (m_parent->Cursor() && !p_event.ShiftDown()) { bool c = false; // set to true if cursor position has changed switch (p_event.KeyCode()) { case WXK_LEFT: if (m_parent->Cursor()->GetParent()) { m_parent->SetCursor(m_layout.GetValidParent(m_parent->Cursor())->GetNode()); c = true; } break; case WXK_RIGHT: if (m_layout.GetValidChild(m_parent->Cursor())) { m_parent->SetCursor(m_layout.GetValidChild(m_parent->Cursor())->GetNode()); c = true; } break; case WXK_UP: { Node *prior = ((!p_event.ControlDown()) ? m_layout.PriorSameLevel(m_parent->Cursor()) : PriorSameIset(m_parent->Cursor())); if (prior) { m_parent->SetCursor(prior); c = true; } break; } case WXK_DOWN: { Node *next = ((!p_event.ControlDown()) ? m_layout.NextSameLevel(m_parent->Cursor()) : NextSameIset(m_parent->Cursor())); if (next) { m_parent->SetCursor(next); c = true; } break; } case WXK_SPACE: // Force a scroll to be sure selected node is visible c = true; break; } if (c) { ProcessCursor(); // cursor moved } } else { p_event.Skip(); }}//---------------------------------------------------------------------// TreeWindow: Drawing functions//---------------------------------------------------------------------void TreeWindow::RefreshTree(void){ m_layout.BuildNodeList(*m_parent->GetSupport()); m_layout.Layout(*m_parent->GetSupport()); AdjustScrollbarSteps();}void TreeWindow::RefreshLayout(void){ m_layout.Layout(*m_parent->GetSupport()); AdjustScrollbarSteps();}void TreeWindow::RefreshLabels(void){ m_layout.GenerateLabels(); Refresh();}void TreeWindow::SetCutNode(Node *p_node, bool p_cut){ m_layout.SetCutNode(p_node, p_cut);}void TreeWindow::AdjustScrollbarSteps(void){ int width, height; GetClientSize(&width, &height); int scrollX, scrollY; GetViewStart(&scrollX, &scrollY); const int OUTCOME_LENGTH = 60; SetScrollbars(50, 50, (int) ((m_layout.MaxX() + m_drawSettings.NodeSize() + OUTCOME_LENGTH) * m_zoom / 50 + 1), (int) (m_layout.MaxY() * m_zoom / 50 + 1), scrollX, scrollY);}void TreeWindow::FitZoom(void){ int width, height; GetClientSize(&width, &height); double zoomx = (double) width / (double) m_layout.MaxX(); double zoomy = (double) height / (double) m_layout.MaxY(); zoomx = gmin(zoomx, 1.0); zoomy = gmin(zoomy, 1.0); // never zoom in (only out) m_zoom = gmin(zoomx, zoomy) * .9;}void TreeWindow::SetZoom(double p_zoom){ m_zoom = p_zoom; AdjustScrollbarSteps(); EnsureCursorVisible(); Refresh();}void TreeWindow::OnDraw(wxDC &dc){ if (m_parent->Cursor()) { if (!m_layout.GetNodeEntry(m_parent->Cursor())) { m_parent->SetCursor(m_efg.RootNode()); } UpdateCursor(); } dc.SetUserScale(m_zoom, m_zoom); dc.BeginDrawing(); dc.Clear(); m_layout.Render(dc); dc.EndDrawing();}void TreeWindow::OnDraw(wxDC &p_dc, double p_zoom){ // Bit of a hack: this allows us to set zoom separately in printout code double saveZoom = m_zoom; m_zoom = p_zoom; OnDraw(p_dc); m_zoom = saveZoom;}void TreeWindow::EnsureCursorVisible(void){ if (!m_parent->Cursor()) { return; } NodeEntry *entry = m_layout.GetNodeEntry(m_parent->Cursor()); int xScroll, yScroll; GetViewStart(&xScroll, &yScroll); int width, height; GetClientSize(&width, &height); int xx, yy; CalcScrolledPosition((int) (entry->X() * m_zoom - 20), (int) (entry->Y() * m_zoom), &xx, &yy); if (xx < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -