Logo Search packages:      
Sourcecode: vegastrike version File versions  Download package

navcomputer.cpp

/* 
 * Vega Strike
 * Copyright (C) 2003 Mike Byron
 * 
 * http://vegastrike.sourceforge.net/
 *
 * 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 "vegastrike.h"
#if defined( _WIN32) && !defined(__CYGWIN__) && !defined( __MINGW32__)
// For WIN32 debugging.
#include <crtdbg.h>
#endif

#include "navcomputer.h"
#include "navpath.h"
#include "in_kb.h"
#include "in_kb_data.h"
#include "in_mouse.h"
#include "gfx/cockpit.h"
#include "main_loop.h"
#include "lin_time.h"
#include "gui/modaldialog.h"
#include "gui/eventmanager.h"
#include "gui/newbutton.h"
#include "gui/staticdisplay.h"
#include "gui/textinputdisplay.h"
#include "gui/simplepicker.h"
#include "gui/groupcontrol.h"
#include "gui/scroller.h"

vector<unsigned int > nav_keyboard_queue;

using namespace std;

// The separator used between categories in a category string.
static const char CATEGORY_SEP = '/';
// Tag that says this is a category not an item.
static const char CATEGORY_TAG = (-1);
// Space between mode buttons.
static const float MODE_BUTTON_SPACE = 0.03;

// Info about each mode.
struct ModeInfo {
  string title;
  string button;
  string command;
  string groupId;
  ModeInfo(string t="", string b="", string c="", string g="")
    : title(t), button(b), command(c), groupId(g) {
  }
};

static const ModeInfo displayModeInfo[] = {
  ModeInfo ( "List Mode", "Finished", "ListMode", "ListGroup" ),
  ModeInfo ( "Edit Mode", "Edit", "EditMode", "EditGroup" )
};

static const ModeInfo selectorModeInfo[] = {
  ModeInfo ( "Target Select", "System", "TargetSelectMode", "TargetSelectGroup" ),
  ModeInfo ( "Criteria Select", "Criteria", "CriteriaSelectMode", "CriteriaSelectGroup" ),
  ModeInfo ( "Chain Select", "Chain", "ChainSelectMode", "ChainSelectGroup" )
};

// Dispatch table for commands.
// Make an entry here for each command you want to handle.
// WARNING:  The order of this table is important.  There are multiple entries for
//  some commands. Basically, you can make an entry for a particular control, and then
//  later have an entry with an empty control id to cover the other cases.
const NavComputer::WctlTableEntry NavComputer::WctlCommandTable[] = {
  NavComputer::WctlTableEntry ( "Visible", "", &NavComputer::toggleVisibility ),
  NavComputer::WctlTableEntry ( "Picker::NewSelection", "PathLister", &NavComputer::pathListerChangedSelection ), 
  NavComputer::WctlTableEntry ( displayModeInfo[LIST].command, "", &NavComputer::changeToListMode ),
  NavComputer::WctlTableEntry ( displayModeInfo[EDIT].command, "", &NavComputer::changeToEditMode ),
  NavComputer::WctlTableEntry ( selectorModeInfo[TARGET].command, "", &NavComputer::changeToTargetMode ),
  NavComputer::WctlTableEntry ( selectorModeInfo[CRITERIA].command, "", &NavComputer::changeToCriteriaMode ),
  NavComputer::WctlTableEntry ( selectorModeInfo[CHAIN].command, "", &NavComputer::changeToChainMode ),
  NavComputer::WctlTableEntry ( "Add", "", &NavComputer::actionAdd ),
  NavComputer::WctlTableEntry ( "ShowPath", "", &NavComputer::actionShowPath ),
  NavComputer::WctlTableEntry ( "Rename", "", &NavComputer::actionRename ),
  NavComputer::WctlTableEntry ( "Remove", "", &NavComputer::actionRemove ),
  NavComputer::WctlTableEntry ( "ShowAll", "", &NavComputer::actionShowAll ),
  NavComputer::WctlTableEntry ( "ShowNone", "", &NavComputer::actionShowNone ),
  NavComputer::WctlTableEntry ( "Source", "", &NavComputer::actionSource ),
  NavComputer::WctlTableEntry ( "Destination", "", &NavComputer::actionDestination ),
  NavComputer::WctlTableEntry ( "Target", "", &NavComputer::actionTarget ),
  NavComputer::WctlTableEntry ( "Current", "", &NavComputer::actionCurrent ),
  NavComputer::WctlTableEntry ( "Absolute", "", &NavComputer::actionAbsolute ),
  NavComputer::WctlTableEntry ( "And", "", &NavComputer::actionAnd ),
  NavComputer::WctlTableEntry ( "Or", "", &NavComputer::actionOr ),
  NavComputer::WctlTableEntry ( "Not", "", &NavComputer::actionNot ),
  NavComputer::WctlTableEntry ( "RemoveCriteria", "", &NavComputer::actionRemoveCriteria ),
  NavComputer::WctlTableEntry ( "Chain", "", &NavComputer::actionChain ),
  NavComputer::WctlTableEntry ( "", "", NULL )
};

// Process a command from the window.
// This just dispatches to a handler.
bool NavComputer::processWindowCommand(const EventCommandId& command, Control* control) {

  // Iterate through the dispatch table.
  for(const WctlTableEntry *p = &WctlCommandTable[0]; p->function ; p++) {
    if(p->command == command) {
      if(p->controlId.size() == 0 || p->controlId == control->id()) {
      // Found a handler for the command.
      return( (this->*(p->function))(command, control) );
      }
    }
  }

  // Let the base class have a try at the command first.
  if(WindowController::processWindowCommand(command, control)) {
    return true;
  }

  // Didn't find a handler.
  return false;
};

// CONSTRUCTOR.
NavComputer::NavComputer(NavigationSystem *navsystem)
  : 
  navsys(navsystem),
  m_currentDisplay(NULL_DISPLAY),
  m_currentSelector(NULL_SELECTOR)
{
  pathman=navsystem->pathman;
  currentPath=NULL;
  currentNode=NULL;
  criteria=false;

  // Initialize display mode group controls array.
  for(int i=0; i<DISPLAY_MODE_COUNT; i++) {
    m_displayModeGroups[i] = NULL;
  }

  // Initialize selector mode group controls array.
  for(int i=0; i<SELECTOR_MODE_COUNT; i++) {
    m_selectorModeGroups[i] = NULL;
  }

  m_displayModes.push_back(LIST);
  m_displayModes.push_back(EDIT);

  m_selectorModes.push_back(TARGET);
  m_selectorModes.push_back(CRITERIA);
  m_selectorModes.push_back(CHAIN);

  m_visible = false;
}

// Destructor.
NavComputer::~NavComputer(void) {
  // Delete any group controls that the window doesn't "own".
  for(int i=0; i<DISPLAY_MODE_COUNT; i++) {
    if(m_displayModeGroups[i] != NULL) {
      delete m_displayModeGroups[i];
    }
  }
    
  for(int i=0; i<SELECTOR_MODE_COUNT; i++) {
    if(m_selectorModeGroups[i] != NULL) {
      delete m_selectorModeGroups[i];
    }
  }
}

// Set up the window and get everything ready.
void NavComputer::init(void) {
  // Create a new window.
  Window* w = new Window;
  setWindow(w);

  m_window->setDeleteOnClose(false);
  m_window->setController(this);
  m_deleteOnWindowClose = false;

  // Read in the controls for all the modes.
  createControls();

  NavPath *path = new NavPath();
  path->setName("Target Search");
  path->setSourceNode(new CurrentPathNode());
  path->setDestinationNode(new TargetPathNode());
  pathman->paths.push_back(path);
}

// Create the controls that will be used for this window.
void NavComputer::createControls(void) {
  // Set up the window.
  window()->setFullScreen();
  window()->setColor(GUI_CLEAR);
  window()->setTexture("basecomputer.png");

  // Put all the controls in the window.
  constructControls();

  // Take the mode group controls out of the window.
  for(int i=0; i<DISPLAY_MODE_COUNT; i++) {
    Control* group = window()->findControlById(displayModeInfo[i].groupId);
    if(group) {
      window()->removeControlFromWindow(group);
      m_displayModeGroups[i] = group;
    }
  }

  // Take the mode group controls out of the window.
  for(int i=0; i<SELECTOR_MODE_COUNT; i++) {
    Control* group = window()->findControlById(selectorModeInfo[i].groupId);
    if(group) {
      window()->removeControlFromWindow(group);
      m_selectorModeGroups[i] = group;
    }
  }
}

GFXColor NavComputer::getColorForGroup(std::string id) {
  if (id=="MainGroup") {
    return GFXColor(0,1,1);
  } else if (id=="ListGroup") {
    return GFXColor(0,1,1);
  } else if (id=="EditGroup") {
    return GFXColor(0,1,1);
  } else {
    return GFXColor(0,1,1);
  }
}

// Hack that constructs controls in code.
void NavComputer::constructControls(void) {
  {
    GroupControl * mainGroup = new GroupControl;
    mainGroup->setId("MainGroup");
    window()->addControl(mainGroup);
    GFXColor color=getColorForGroup("MainGroup");

    // Base info title.
    StaticDisplay* baseTitle = new StaticDisplay;
    baseTitle->setRect( Rect(-.96, .76, 1.9, .08) );
    baseTitle->setText("Error");
    baseTitle->setTextColor(GFXColor(.4,1,.4));
    baseTitle->setColor(GUI_CLEAR);
    baseTitle->setFont( Font(.07, 1.75) );
    baseTitle->setId("NavigationTitle");
    mainGroup->addChild(baseTitle);
      
    // Done button.
    NewButton* done = new NewButton;
    done->setRect( Rect(.74, .74, .22, .12) );
    done->setLabel("Done");
    done->setCommand("Visible");
    done->setColor( GFXColor(0,1,1,.25) );
    done->setTextColor( GUI_OPAQUE_WHITE() );
    done->setDownColor( GFXColor(0,1,1,.6) );
    done->setDownTextColor( GUI_OPAQUE_BLACK() );
    done->setHighlightColor( GFXColor(0,0,1,.4) );
    done->setFont(Font(.08, BOLD_STROKE));
    mainGroup->addChild(done);
      
    // Scroller for description.
    Scroller* descScroller = new Scroller;
    descScroller->setRect( Rect(.91, -.29, .05, .99) );
    descScroller->setColor( GFXColor(color.r,color.g,color.b,.1) );
    descScroller->setThumbColor( GFXColor(color.r*.4,color.g*.4,color.b*.4), GUI_OPAQUE_WHITE() );
    descScroller->setButtonColor( GFXColor(color.r*.4,color.g*.4,color.b*.4) );
    descScroller->setTextColor(GUI_OPAQUE_WHITE());
    descScroller->setOutlineColor(GUI_OPAQUE_MEDIUM_GRAY());
      
    // Description box.
    StaticDisplay* ms = new StaticDisplay;
    ms->setRect( Rect(.24, -.29, .67, .99) );
    ms->setColor( GFXColor(color.r,color.g,color.b,.1) );
    ms->setOutlineColor(GUI_OPAQUE_MEDIUM_GRAY());
    ms->setFont( Font(.07) );
    ms->setMultiLine(true);
    ms->setTextColor(GUI_OPAQUE_WHITE());
    ms->setTextMargins(Size(.02,.01));
    ms->setId("Description");
    ms->setScroller(descScroller);
    mainGroup->addChild(ms);
      
    mainGroup->addChild(descScroller);    // Want scroller "over" description box.
  }

  {
    GroupControl * listGroup = new GroupControl;
    listGroup->setId(displayModeInfo[LIST].groupId);
    window()->addControl(listGroup);
    GFXColor color=getColorForGroup(displayModeInfo[LIST].groupId);

    // Scroller for picker.
    Scroller* pathScroller = new Scroller;
    pathScroller->setRect( Rect(-.50, -.95, .05, 1.65) );
    pathScroller->setColor( GFXColor(color.r,color.g,color.b,.1) );
    pathScroller->setThumbColor( GFXColor(color.r*.4,color.g*.4,color.b*.4), GUI_OPAQUE_WHITE() );
    pathScroller->setButtonColor( GFXColor(color.r*.4,color.g*.4,color.b*.4) );
    pathScroller->setTextColor(GUI_OPAQUE_WHITE());
    pathScroller->setOutlineColor(GUI_OPAQUE_MEDIUM_GRAY());

    // Save game picker.
    SimplePicker* pathList = new SimplePicker;
    pathList->setRect( Rect(-.96, -.95, .46, 1.65) );
    pathList->setColor( GFXColor(color.r,color.g,color.b,.1) );
    pathList->setOutlineColor(GUI_OPAQUE_MEDIUM_GRAY());
    pathList->setTextColor(GUI_OPAQUE_WHITE());
    pathList->setSelectionColor(GFXColor(0,.6,0,.8));
    pathList->setHighlightColor(GFXColor(0,.6,0,.35));
    pathList->setHighlightTextColor(GUI_OPAQUE_WHITE());
    pathList->setFont( Font(.07) );
    pathList->setTextMargins(Size(0.02,0.01));
    pathList->setId("PathLister");
    pathList->setScroller(pathScroller);
    listGroup->addChild(pathList);

    listGroup->addChild(pathScroller);          // Want scroller "over" picker.


    NewButton * up = new NewButton;
    up->setRect(Rect(-.41, .58, .22, .12) );
    up->setColor( GFXColor(0,1,1,.1) );
    up->setTextColor(GUI_OPAQUE_WHITE());
    up->setDownColor( GFXColor(0,1,1,.4) );
    up->setDownTextColor( GFXColor(.2,.2,.2) );
    up->setVariableBorderCycleTime(1.0);
    up->setBorderColor( GFXColor(.2,.2,.2) );
    up->setEndBorderColor( GFXColor(.4,.4,.4) );
    up->setShadowWidth(2.0);
    up->setFont(Font(.08, BOLD_STROKE));
    up->setId("Up");
    up->setLabel("Up");
    up->setCommand("Up");
    listGroup->addChild(up);
      
    NewButton * add = new NewButton;
    add->setRect(Rect(-.41, .33, .22, .12) );
    add->setColor( GFXColor(0,1,1,.1) );
    add->setTextColor(GUI_OPAQUE_WHITE());
    add->setDownColor( GFXColor(0,1,1,.4) );
    add->setDownTextColor( GFXColor(.2,.2,.2) );
    add->setVariableBorderCycleTime(1.0);
    add->setBorderColor( GFXColor(.2,.2,.2) );
    add->setEndBorderColor( GFXColor(.4,.4,.4) );
    add->setShadowWidth(2.0);
    add->setFont(Font(.08, BOLD_STROKE));
    add->setId("Add");
    add->setLabel("Add");
    add->setCommand("Add");
    listGroup->addChild(add);

    NewButton * edit = new NewButton;
    edit->setRect(Rect(-.41, .07, .22, .12) );
    edit->setColor( GFXColor(0,1,1,.1) );
    edit->setTextColor(GUI_OPAQUE_WHITE());
    edit->setDownColor( GFXColor(0,1,1,.4) );
    edit->setDownTextColor( GFXColor(.2,.2,.2) );
    edit->setVariableBorderCycleTime(1.0);
    edit->setBorderColor( GFXColor(.2,.2,.2) );
    edit->setEndBorderColor( GFXColor(.4,.4,.4) );
    edit->setShadowWidth(2.0);
    edit->setFont(Font(.08, BOLD_STROKE));
    edit->setId(displayModeInfo[EDIT].button);
    edit->setLabel(displayModeInfo[EDIT].button);
    edit->setCommand(displayModeInfo[EDIT].command);
    listGroup->addChild(edit);

    NewButton* showpath = new NewButton;
    showpath->setRect( Rect(-.41,-.18, .22, .12) );
    showpath->setColor( GFXColor(0,1,1,.1) );
    showpath->setTextColor(GUI_OPAQUE_WHITE());
    showpath->setDownColor( GFXColor(0,1,1,.4) );
    showpath->setDownTextColor( GFXColor(.2,.2,.2) );
    showpath->setVariableBorderCycleTime(1.0);
    showpath->setBorderColor( GFXColor(.2,.2,.2) );
    showpath->setEndBorderColor( GFXColor(.4,.4,.4) );
    showpath->setShadowWidth(2.0);
    showpath->setFont(Font(.08, BOLD_STROKE));
    showpath->setId("ShowPath");
    showpath->setLabel("Show");
    showpath->setCommand("ShowPath");
    listGroup->addChild(showpath);

    NewButton* rename = new NewButton;
    rename->setRect( Rect(-.41,-.44, .22, .12) );
    rename->setColor( GFXColor(0,1,1,.1) );
    rename->setTextColor(GUI_OPAQUE_WHITE());
    rename->setDownColor( GFXColor(0,1,1,.4) );
    rename->setDownTextColor( GFXColor(.2,.2,.2) );
    rename->setVariableBorderCycleTime(1.0);
    rename->setBorderColor( GFXColor(.2,.2,.2) );
    rename->setEndBorderColor( GFXColor(.4,.4,.4) );
    rename->setShadowWidth(2.0);
    rename->setFont(Font(.08, BOLD_STROKE));
    rename->setId("Rename");
    rename->setLabel("Rename");
    rename->setCommand("Rename");
    listGroup->addChild(rename);

    NewButton* remove = new NewButton;
    remove->setRect( Rect(-.41,-.69, .22, .12) );
    remove->setColor( GFXColor(0,1,1,.1) );
    remove->setTextColor(GUI_OPAQUE_WHITE());
    remove->setDownColor( GFXColor(0,1,1,.4) );
    remove->setDownTextColor( GFXColor(.2,.2,.2) );
    remove->setVariableBorderCycleTime(1.0);
    remove->setBorderColor( GFXColor(.2,.2,.2) );
    remove->setEndBorderColor( GFXColor(.4,.4,.4) );
    remove->setShadowWidth(2.0);
    remove->setFont(Font(.08, BOLD_STROKE));
    remove->setId("Remove");
    remove->setLabel("Remove");
    remove->setCommand("Remove");
    listGroup->addChild(remove);

    NewButton* down = new NewButton;
    down->setRect( Rect(-.41,-.95, .22, .12) );
    down->setColor( GFXColor(0,1,1,.1) );
    down->setTextColor(GUI_OPAQUE_WHITE());
    down->setDownColor( GFXColor(0,1,1,.4) );
    down->setDownTextColor( GFXColor(.2,.2,.2) );
    down->setVariableBorderCycleTime(1.0);
    down->setBorderColor( GFXColor(.2,.2,.2) );
    down->setEndBorderColor( GFXColor(.4,.4,.4) );
    down->setShadowWidth(2.0);
    down->setFont(Font(.08, BOLD_STROKE));
    down->setId("Down");
    down->setLabel("Down");
    down->setCommand("Down");
    listGroup->addChild(down);


    NewButton* showall = new NewButton;
    showall->setRect( Rect(-.15, .58, .35, .12) );
    showall->setColor( GFXColor(0,1,1,.1) );
    showall->setTextColor(GUI_OPAQUE_WHITE());
    showall->setDownColor( GFXColor(0,1,1,.4) );
    showall->setDownTextColor( GFXColor(.2,.2,.2) );
    showall->setVariableBorderCycleTime(1.0);
    showall->setBorderColor( GFXColor(.2,.2,.2) );
    showall->setEndBorderColor( GFXColor(.4,.4,.4) );
    showall->setShadowWidth(2.0);
    showall->setFont(Font(.08, BOLD_STROKE));
    showall->setId("ShowAll");
    showall->setLabel("Show All");
    showall->setCommand("ShowAll");
    listGroup->addChild(showall);

    NewButton* shownone = new NewButton;
    shownone->setRect( Rect(-.15, .33, .35, .12) );
    shownone->setColor( GFXColor(0,1,1,.1) );
    shownone->setTextColor(GUI_OPAQUE_WHITE());
    shownone->setDownColor( GFXColor(0,1,1,.4) );
    shownone->setDownTextColor( GFXColor(.2,.2,.2) );
    shownone->setVariableBorderCycleTime(1.0);
    shownone->setBorderColor( GFXColor(.2,.2,.2) );
    shownone->setEndBorderColor( GFXColor(.4,.4,.4) );
    shownone->setShadowWidth(2.0);
    shownone->setFont(Font(.08, BOLD_STROKE));
    shownone->setId("ShowNone");
    shownone->setLabel("Show None");
    shownone->setCommand("ShowNone");
    listGroup->addChild(shownone);
  }

  {
    GroupControl * editGroup = new GroupControl;
    editGroup->setId(displayModeInfo[EDIT].groupId);
    window()->addControl(editGroup);
    GFXColor color=getColorForGroup(displayModeInfo[EDIT].groupId);

    // Apply hint title.
    StaticDisplay* applyHint = new StaticDisplay;
    applyHint->setRect( Rect(-.96, .56, .26, .20) );
    applyHint->setText("Apply To:");
    applyHint->setTextColor(GFXColor(.4,1,.4));
    applyHint->setColor(GUI_CLEAR);
    applyHint->setFont( Font(.07, 1.75) );
    applyHint->setId("ApplyHint");
    editGroup->addChild(applyHint);
      
    NewButton * source = new NewButton;
    source->setRect(Rect(-.66, .50, .40, .20) );
    source->setColor( GFXColor(0,1,1,.1) );
    source->setTextColor(GUI_OPAQUE_WHITE());
    source->setDownColor( GFXColor(0,1,1,.4) );
    source->setDownTextColor( GFXColor(.2,.2,.2) );
    source->setVariableBorderCycleTime(1.0);
    source->setBorderColor( GFXColor(.2,.2,.2) );
    source->setEndBorderColor( GFXColor(.4,.4,.4) );
    source->setShadowWidth(2.0);
    source->setFont(Font(.08, BOLD_STROKE));
    source->setId("Source");
    source->setLabel("Source");
    source->setCommand("Source");
    editGroup->addChild(source);
      
    NewButton * destination = new NewButton;
    destination->setRect(Rect(-.20, .50, .40, .20) );
    destination->setColor( GFXColor(0,1,1,.1) );
    destination->setTextColor(GUI_OPAQUE_WHITE());
    destination->setDownColor( GFXColor(0,1,1,.4) );
    destination->setDownTextColor( GFXColor(.2,.2,.2) );
    destination->setVariableBorderCycleTime(1.0);
    destination->setBorderColor( GFXColor(.2,.2,.2) );
    destination->setEndBorderColor( GFXColor(.4,.4,.4) );
    destination->setShadowWidth(2.0);
    destination->setFont(Font(.08, BOLD_STROKE));
    destination->setId("Destination");
    destination->setLabel("Destination");
    destination->setCommand("Destination");
    editGroup->addChild(destination);



    NewButton * targetMode = new NewButton;
    targetMode->setRect(Rect(-.96, .26, .22, .12) );
    targetMode->setColor( GFXColor(0,1,1,.1) );
    targetMode->setTextColor(GUI_OPAQUE_WHITE());
    targetMode->setDownColor( GFXColor(0,1,1,.4) );
    targetMode->setDownTextColor( GFXColor(.2,.2,.2) );
    targetMode->setVariableBorderCycleTime(1.0);
    targetMode->setBorderColor( GFXColor(.2,.2,.2) );
    targetMode->setEndBorderColor( GFXColor(.4,.4,.4) );
    targetMode->setShadowWidth(2.0);
    targetMode->setFont(Font(.08, BOLD_STROKE));
    targetMode->setId(selectorModeInfo[TARGET].button);
    targetMode->setLabel(selectorModeInfo[TARGET].button);
    targetMode->setCommand(selectorModeInfo[TARGET].command);
    editGroup->addChild(targetMode);

    NewButton* stringMode = new NewButton;
    stringMode->setRect( Rect(-.96,-.04, .22, .12) );
    stringMode->setColor( GFXColor(0,1,1,.1) );
    stringMode->setTextColor(GUI_OPAQUE_WHITE());
    stringMode->setDownColor( GFXColor(0,1,1,.4) );
    stringMode->setDownTextColor( GFXColor(.2,.2,.2) );
    stringMode->setVariableBorderCycleTime(1.0);
    stringMode->setBorderColor( GFXColor(.2,.2,.2) );
    stringMode->setEndBorderColor( GFXColor(.4,.4,.4) );
    stringMode->setShadowWidth(2.0);
    stringMode->setFont(Font(.08, BOLD_STROKE));
    stringMode->setId(selectorModeInfo[CRITERIA].button);
    stringMode->setLabel(selectorModeInfo[CRITERIA].button);
    stringMode->setCommand(selectorModeInfo[CRITERIA].command);
    editGroup->addChild(stringMode);

    NewButton* chainMode = new NewButton;
    chainMode->setRect( Rect(-.96,-.34, .22, .12) );
    chainMode->setColor( GFXColor(0,1,1,.1) );
    chainMode->setTextColor(GUI_OPAQUE_WHITE());
    chainMode->setDownColor( GFXColor(0,1,1,.4) );
    chainMode->setDownTextColor( GFXColor(.2,.2,.2) );
    chainMode->setVariableBorderCycleTime(1.0);
    chainMode->setBorderColor( GFXColor(.2,.2,.2) );
    chainMode->setEndBorderColor( GFXColor(.4,.4,.4) );
    chainMode->setShadowWidth(2.0);
    chainMode->setFont(Font(.08, BOLD_STROKE));
    chainMode->setId(selectorModeInfo[CHAIN].button);
    chainMode->setLabel(selectorModeInfo[CHAIN].button);
    chainMode->setCommand(selectorModeInfo[CHAIN].command);
    editGroup->addChild(chainMode);

    NewButton* finished = new NewButton;
    finished->setRect( Rect(-.96,-.64, .22, .12) );
    finished->setColor( GFXColor(0,1,1,.1) );
    finished->setTextColor(GUI_OPAQUE_WHITE());
    finished->setDownColor( GFXColor(0,1,1,.4) );
    finished->setDownTextColor( GFXColor(.2,.2,.2) );
    finished->setVariableBorderCycleTime(1.0);
    finished->setBorderColor( GFXColor(.2,.2,.2) );
    finished->setEndBorderColor( GFXColor(.4,.4,.4) );
    finished->setShadowWidth(2.0);
    finished->setFont(Font(.08, BOLD_STROKE));
    finished->setId(displayModeInfo[LIST].button);
    finished->setLabel(displayModeInfo[LIST].button);
    finished->setCommand(displayModeInfo[LIST].command);
    editGroup->addChild(finished);

    // Scroller for description.
    Scroller* descScroller = new Scroller;
    descScroller->setRect( Rect(.91, -.95, .05, .62) );
    descScroller->setColor( GFXColor(color.r,color.g,color.b,.1) );
    descScroller->setThumbColor( GFXColor(color.r*.4,color.g*.4,color.b*.4), GUI_OPAQUE_WHITE() );
    descScroller->setButtonColor( GFXColor(color.r*.4,color.g*.4,color.b*.4) );
    descScroller->setTextColor(GUI_OPAQUE_WHITE());
    descScroller->setOutlineColor(GUI_OPAQUE_MEDIUM_GRAY());
      
    // Description box.
    StaticDisplay* ms = new StaticDisplay;
    ms->setRect( Rect(.24, -.95, .67, .62) );
    ms->setColor( GFXColor(color.r,color.g,color.b,.1) );
    ms->setOutlineColor(GUI_OPAQUE_MEDIUM_GRAY());
    ms->setFont( Font(.07) );
    ms->setMultiLine(true);
    ms->setTextColor(GUI_OPAQUE_WHITE());
    ms->setTextMargins(Size(.02,.01));
    ms->setId("NodeDescription");
    ms->setScroller(descScroller);
    editGroup->addChild(ms);
      
    editGroup->addChild(descScroller);    // Want scroller "over" description box.

  }

  {
    GroupControl * targetGroup = new GroupControl;
    targetGroup->setId(selectorModeInfo[TARGET].groupId);
    window()->addControl(targetGroup);
    GFXColor color=getColorForGroup(selectorModeInfo[TARGET].groupId);

    NewButton * absolute = new NewButton;
    absolute->setRect(Rect(-.56, .26, .61, .12) );
    absolute->setColor( GFXColor(0,1,1,.1) );
    absolute->setTextColor(GUI_OPAQUE_WHITE());
    absolute->setDownColor( GFXColor(0,1,1,.4) );
    absolute->setDownTextColor( GFXColor(.2,.2,.2) );
    absolute->setVariableBorderCycleTime(1.0);
    absolute->setBorderColor( GFXColor(.2,.2,.2) );
    absolute->setEndBorderColor( GFXColor(.4,.4,.4) );
    absolute->setShadowWidth(2.0);
    absolute->setFont(Font(.08, BOLD_STROKE));
    absolute->setId("Absolute");
    absolute->setLabel("ERROR");
    absolute->setCommand("Absolute");
    targetGroup->addChild(absolute);

    NewButton * target = new NewButton;
    target->setRect(Rect(-.56, .10, .61, .12) );
    target->setColor( GFXColor(0,1,1,.1) );
    target->setTextColor(GUI_OPAQUE_WHITE());
    target->setDownColor( GFXColor(0,1,1,.4) );
    target->setDownTextColor( GFXColor(.2,.2,.2) );
    target->setVariableBorderCycleTime(1.0);
    target->setBorderColor( GFXColor(.2,.2,.2) );
    target->setEndBorderColor( GFXColor(.4,.4,.4) );
    target->setShadowWidth(2.0);
    target->setFont(Font(.08, BOLD_STROKE));
    target->setId("Target");
    target->setLabel("Target");
    target->setCommand("Target");
    targetGroup->addChild(target);
      
    NewButton * current = new NewButton;
    current->setRect(Rect(-.56, -.06, .61, .12) );
    current->setColor( GFXColor(0,1,1,.1) );
    current->setTextColor(GUI_OPAQUE_WHITE());
    current->setDownColor( GFXColor(0,1,1,.4) );
    current->setDownTextColor( GFXColor(.2,.2,.2) );
    current->setVariableBorderCycleTime(1.0);
    current->setBorderColor( GFXColor(.2,.2,.2) );
    current->setEndBorderColor( GFXColor(.4,.4,.4) );
    current->setShadowWidth(2.0);
    current->setFont(Font(.08, BOLD_STROKE));
    current->setId("Current");
    current->setLabel("Current");
    current->setCommand("Current");
    targetGroup->addChild(current);
  }

  {
    GroupControl * criteriaGroup = new GroupControl;
    criteriaGroup->setId(selectorModeInfo[CRITERIA].groupId);
    window()->addControl(criteriaGroup);
    GFXColor color=getColorForGroup(selectorModeInfo[CRITERIA].groupId);

    // Scroller for picker.
    Scroller* parameterScroller = new Scroller;
    parameterScroller->setRect( Rect(.15, .15, .05, .23) );
    parameterScroller->setColor( GFXColor(color.r,color.g,color.b,.1) );
    parameterScroller->setThumbColor( GFXColor(color.r*.4,color.g*.4,color.b*.4), GUI_OPAQUE_WHITE() );
    parameterScroller->setButtonColor( GFXColor(color.r*.4,color.g*.4,color.b*.4) );
    parameterScroller->setTextColor(GUI_OPAQUE_WHITE());
    parameterScroller->setOutlineColor(GUI_OPAQUE_MEDIUM_GRAY());

    // Parameter picker.
    SimplePicker* parameterList = new SimplePicker;
    parameterList->setRect( Rect(-.66, .15, .81, .23) );
    parameterList->setColor( GFXColor(color.r,color.g,color.b,.1) );
    parameterList->setOutlineColor(GUI_OPAQUE_MEDIUM_GRAY());
    parameterList->setTextColor(GUI_OPAQUE_WHITE());
    parameterList->setSelectionColor(GFXColor(0,.6,0,.8));
    parameterList->setHighlightColor(GFXColor(0,.6,0,.35));
    parameterList->setHighlightTextColor(GUI_OPAQUE_WHITE());
    parameterList->setFont( Font(.07) );
    parameterList->setTextMargins(Size(0.02,0.01));
    parameterList->setId("ParameterLister");
    parameterList->setScroller(parameterScroller);
    criteriaGroup->addChild(parameterList);
    parameterList->clear();
    parameterList->addCell(new ValuedPickerCell<CriteriaType>(CONTAINS, "Contains"));
    parameterList->addCell(new ValuedPickerCell<CriteriaType>(OWNEDBY, "Owned By"));
    parameterList->addCell(new ValuedPickerCell<CriteriaType>(SECTOR, "Sector"));

    criteriaGroup->addChild(parameterScroller);       // Want scroller "over" picker.
    


    // Parameter value box.
    StaticDisplay* valueBox = new TextInputDisplay(&nav_keyboard_queue,"\x1b\n\t\r\\/&|:<>\"^");
    valueBox->setRect( Rect(-.66, .01, .86, .10 ) );
    valueBox->setColor( GFXColor(color.r,color.g,color.b,.1) );
    valueBox->setOutlineColor(GUI_OPAQUE_MEDIUM_GRAY());
    valueBox->setFont( Font(.07) );
    valueBox->setMultiLine(true);
    valueBox->setTextColor(GUI_OPAQUE_WHITE());
    valueBox->setTextMargins(Size(.02,.01));
    valueBox->setId("ParameterValueBox");
    criteriaGroup->addChild(valueBox);

    NewButton * andButton = new NewButton;
    andButton->setRect(Rect(-.66, -.15, .22, .12) );
    andButton->setColor( GFXColor(0,1,1,.1) );
    andButton->setTextColor(GUI_OPAQUE_WHITE());
    andButton->setDownColor( GFXColor(0,1,1,.4) );
    andButton->setDownTextColor( GFXColor(.2,.2,.2) );
    andButton->setVariableBorderCycleTime(1.0);
    andButton->setBorderColor( GFXColor(.2,.2,.2) );
    andButton->setEndBorderColor( GFXColor(.4,.4,.4) );
    andButton->setShadowWidth(2.0);
    andButton->setFont(Font(.08, BOLD_STROKE));
    andButton->setId("And");
    andButton->setLabel("And");
    andButton->setCommand("And");
    criteriaGroup->addChild(andButton);

    NewButton * orButton = new NewButton;
    orButton->setRect(Rect(-.34, -.15, .22, .12) );
    orButton->setColor( GFXColor(0,1,1,.1) );
    orButton->setTextColor(GUI_OPAQUE_WHITE());
    orButton->setDownColor( GFXColor(0,1,1,.4) );
    orButton->setDownTextColor( GFXColor(.2,.2,.2) );
    orButton->setVariableBorderCycleTime(1.0);
    orButton->setBorderColor( GFXColor(.2,.2,.2) );
    orButton->setEndBorderColor( GFXColor(.4,.4,.4) );
    orButton->setShadowWidth(2.0);
    orButton->setFont(Font(.08, BOLD_STROKE));
    orButton->setId("Or");
    orButton->setLabel("Or");
    orButton->setCommand("Or");
    criteriaGroup->addChild(orButton);

    NewButton * notButton = new NewButton;
    notButton->setRect(Rect(-.02, -.15, .22, .12) );
    notButton->setColor( GFXColor(0,1,1,.1) );
    notButton->setTextColor(GUI_OPAQUE_WHITE());
    notButton->setDownColor( GFXColor(0,1,1,.4) );
    notButton->setDownTextColor( GFXColor(.2,.2,.2) );
    notButton->setVariableBorderCycleTime(1.0);
    notButton->setBorderColor( GFXColor(.2,.2,.2) );
    notButton->setEndBorderColor( GFXColor(.4,.4,.4) );
    notButton->setShadowWidth(2.0);
    notButton->setFont(Font(.08, BOLD_STROKE));
    notButton->setId("Not");
    notButton->setLabel("Not");
    notButton->setCommand("Not");
    criteriaGroup->addChild(notButton);

    NewButton * removeButton = new NewButton;
    removeButton->setRect(Rect(-.20, -.31, .40, .12) );
    removeButton->setColor( GFXColor(0,1,1,.1) );
    removeButton->setTextColor(GUI_OPAQUE_WHITE());
    removeButton->setDownColor( GFXColor(0,1,1,.4) );
    removeButton->setDownTextColor( GFXColor(.2,.2,.2) );
    removeButton->setVariableBorderCycleTime(1.0);
    removeButton->setBorderColor( GFXColor(.2,.2,.2) );
    removeButton->setEndBorderColor( GFXColor(.4,.4,.4) );
    removeButton->setShadowWidth(2.0);
    removeButton->setFont(Font(.08, BOLD_STROKE));
    removeButton->setId("RemoveCriteria");
    removeButton->setLabel("Remove");
    removeButton->setCommand("RemoveCriteria");
    criteriaGroup->addChild(removeButton);

    // Scroller for picker.
    Scroller* criteriaScroller = new Scroller;
    criteriaScroller->setRect( Rect(.15, -.95, .05, .60) );
    criteriaScroller->setColor( GFXColor(color.r,color.g,color.b,.1) );
    criteriaScroller->setThumbColor( GFXColor(color.r*.4,color.g*.4,color.b*.4), GUI_OPAQUE_WHITE() );
    criteriaScroller->setButtonColor( GFXColor(color.r*.4,color.g*.4,color.b*.4) );
    criteriaScroller->setTextColor(GUI_OPAQUE_WHITE());
    criteriaScroller->setOutlineColor(GUI_OPAQUE_MEDIUM_GRAY());

    // Criteria picker.
    SimplePicker* criteriaList = new SimplePicker;
    criteriaList->setRect( Rect(-.66, -.95, .81, .60) );
    criteriaList->setColor( GFXColor(color.r,color.g,color.b,.1) );
    criteriaList->setOutlineColor(GUI_OPAQUE_MEDIUM_GRAY());
    criteriaList->setTextColor(GUI_OPAQUE_WHITE());
    criteriaList->setSelectionColor(GFXColor(0,.6,0,.8));
    criteriaList->setHighlightColor(GFXColor(0,.6,0,.35));
    criteriaList->setHighlightTextColor(GUI_OPAQUE_WHITE());
    criteriaList->setFont( Font(.07) );
    criteriaList->setTextMargins(Size(0.02,0.01));
    criteriaList->setId("CriteriaLister");
    criteriaList->setScroller(criteriaScroller);
    criteriaGroup->addChild(criteriaList);

    criteriaGroup->addChild(criteriaScroller);        // Want scroller "over" picker.
  }

  {
    GroupControl * chainGroup = new GroupControl;
    chainGroup->setId(selectorModeInfo[CHAIN].groupId);
    window()->addControl(chainGroup);
    GFXColor color=getColorForGroup(selectorModeInfo[CHAIN].groupId);

    // Scroller for picker.
    Scroller* chainScroller = new Scroller;
    chainScroller->setRect( Rect(.15, -.31, .05, .69) );
    chainScroller->setColor( GFXColor(color.r,color.g,color.b,.1) );
    chainScroller->setThumbColor( GFXColor(color.r*.4,color.g*.4,color.b*.4), GUI_OPAQUE_WHITE() );
    chainScroller->setButtonColor( GFXColor(color.r*.4,color.g*.4,color.b*.4) );
    chainScroller->setTextColor(GUI_OPAQUE_WHITE());
    chainScroller->setOutlineColor(GUI_OPAQUE_MEDIUM_GRAY());

    // Path picker.
    SimplePicker* chainList = new SimplePicker;
    chainList->setRect( Rect(-.66, -.31, .81, .69) );
    chainList->setColor( GFXColor(color.r,color.g,color.b,.1) );
    chainList->setOutlineColor(GUI_OPAQUE_MEDIUM_GRAY());
    chainList->setTextColor(GUI_OPAQUE_WHITE());
    chainList->setSelectionColor(GFXColor(0,.6,0,.8));
    chainList->setHighlightColor(GFXColor(0,.6,0,.35));
    chainList->setHighlightTextColor(GUI_OPAQUE_WHITE());
    chainList->setFont( Font(.07) );
    chainList->setTextMargins(Size(0.02,0.01));
    chainList->setId("ChainLister");
    chainList->setScroller(chainScroller);
    chainGroup->addChild(chainList);

    chainGroup->addChild(chainScroller);        // Want scroller "over" picker.


    // Scroller for picker.
    Scroller* chainTypeScroller = new Scroller;
    chainTypeScroller->setRect( Rect(.15, -.79, .05, .44) );
    chainTypeScroller->setColor( GFXColor(color.r,color.g,color.b,.1) );
    chainTypeScroller->setThumbColor( GFXColor(color.r*.4,color.g*.4,color.b*.4), GUI_OPAQUE_WHITE() );
    chainTypeScroller->setButtonColor( GFXColor(color.r*.4,color.g*.4,color.b*.4) );
    chainTypeScroller->setTextColor(GUI_OPAQUE_WHITE());
    chainTypeScroller->setOutlineColor(GUI_OPAQUE_MEDIUM_GRAY());

    // Type picker.
    SimplePicker* chainTypeList = new SimplePicker;
    chainTypeList->setRect( Rect(-.66, -.79, .81, .44) );
    chainTypeList->setColor( GFXColor(color.r,color.g,color.b,.1) );
    chainTypeList->setOutlineColor(GUI_OPAQUE_MEDIUM_GRAY());
    chainTypeList->setTextColor(GUI_OPAQUE_WHITE());
    chainTypeList->setSelectionColor(GFXColor(0,.6,0,.8));
    chainTypeList->setHighlightColor(GFXColor(0,.6,0,.35));
    chainTypeList->setHighlightTextColor(GUI_OPAQUE_WHITE());
    chainTypeList->setFont( Font(.07) );
    chainTypeList->setTextMargins(Size(0.02,0.01));
    chainTypeList->setId("ChainTypeLister");
    chainTypeList->setScroller(chainTypeScroller);
    chainGroup->addChild(chainTypeList);
    chainTypeList->clear();
    chainTypeList->addCell(new ValuedPickerCell<ChainPathNode::PartType>(ChainPathNode::SOURCE, "Source"));
    chainTypeList->addCell(new ValuedPickerCell<ChainPathNode::PartType>(ChainPathNode::DESTINATION, "Destination"));
    chainTypeList->addCell(new ValuedPickerCell<ChainPathNode::PartType>(ChainPathNode::ALL_POINTS, "All Points"));

    chainGroup->addChild(chainTypeScroller);          // Want scroller "over" picker.


    NewButton * chain = new NewButton;
    chain->setRect(Rect(-.43, -.95, .40, .12) );
    chain->setColor( GFXColor(0,1,1,.1) );
    chain->setTextColor(GUI_OPAQUE_WHITE());
    chain->setDownColor( GFXColor(0,1,1,.4) );
    chain->setDownTextColor( GFXColor(.2,.2,.2) );
    chain->setVariableBorderCycleTime(1.0);
    chain->setBorderColor( GFXColor(.2,.2,.2) );
    chain->setEndBorderColor( GFXColor(.4,.4,.4) );
    chain->setShadowWidth(2.0);
    chain->setFont(Font(.08, BOLD_STROKE));
    chain->setId("Chain");
    chain->setLabel("Chain");
    chain->setCommand("Chain");
    chainGroup->addChild(chain);
  }
}

// Switch to the set of controls used for the specified mode.
void NavComputer::switchToMajorControls(DisplayMode mode) {
  if(m_currentDisplay != mode) {
    assert(m_displayModeGroups[mode] != NULL);         // We should have controls for this mode.

    if(m_currentDisplay != NULL_DISPLAY) {
      // Get the old controls out of the window.
      Control* oldControls = window()->findControlById(displayModeInfo[m_currentDisplay].groupId);
      if(oldControls) {
      window()->removeControlFromWindow(oldControls);
      }
      // We put this back in our table so that we "own" the controls.
      m_displayModeGroups[m_currentDisplay] = oldControls;
    }

    m_currentDisplay = mode;

    window()->addControl(m_displayModeGroups[mode]);
    // Take this group out of our table because we don't own it anymore.
    m_displayModeGroups[mode] = NULL;
      
    recalcTitle();
  }
}

// Switch to the set of controls used for the specified mode.
void NavComputer::switchToMinorControls(SelectorMode mode) {
  if(m_currentSelector != mode) {
    if(m_currentSelector != NULL_SELECTOR) {
      // Get the old controls out of the window.
      Control* oldControls = window()->findControlById(selectorModeInfo[m_currentSelector].groupId);
      if(oldControls) {
      window()->removeControlFromWindow(oldControls);
      }
      // We put this back in our table so that we "own" the controls.
      m_selectorModeGroups[m_currentSelector] = oldControls;
    }

    m_currentSelector = mode;

    if(mode!=NULL_SELECTOR) {
      assert(m_selectorModeGroups[mode] != NULL);         // We should have controls for this mode.
      window()->addControl(m_selectorModeGroups[mode]);
      // Take this group out of our table because we don't own it anymore.
      m_selectorModeGroups[mode] = NULL;
    }
  }
}

// Change display mode to LIST
bool NavComputer::changeToListMode(const EventCommandId& command, Control* control) {
  if(m_currentDisplay != LIST) {
    switchToMinorControls(NULL_SELECTOR);
    switchToMajorControls(LIST);
    loadPathLister();
  }
  return true;
}

// Change display mode to EDIT
bool NavComputer::changeToEditMode(const EventCommandId& command, Control* control) {
  if(m_currentDisplay != EDIT && currentPath!=NULL) {
    switchToMinorControls(NULL_SELECTOR);
    switchToMajorControls(EDIT);
    setCurrentNode();
    criteria=false;
  }
  return true;
}

// Change display mode to TARGET
bool NavComputer::changeToTargetMode(const EventCommandId& command, Control* control) {
  assert(m_currentDisplay == EDIT);         // We should be in edit mode to have chosen a selector
  if(m_currentSelector != TARGET) {
    switchToMinorControls(TARGET);
    loadAbsoluteButton();
  }
  return true;
}

// Change display mode to CRITERIA
bool NavComputer::changeToCriteriaMode(const EventCommandId& command, Control* control) {
  assert(m_currentDisplay == EDIT);         // We should be in edit mode to have chosen a selector
  if(m_currentSelector != CRITERIA) {
    switchToMinorControls(CRITERIA);
    loadCriteriaLister();
  }
  return true;
}

// Change display mode to CHAIN
bool NavComputer::changeToChainMode(const EventCommandId& command, Control* control) {
  assert(m_currentDisplay == EDIT);         // We should be in edit mode to have chosen a selector
  if(m_currentSelector != CHAIN) {
    switchToMinorControls(CHAIN);
    loadChainLister();
  }
  return true;
}

// Open the window, etc.
void NavComputer::run(void) {
  toggleVisibility(EventCommandId(), NULL);
}

void nav_main_loop() {
  GFXBeginScene();
  globalWindowManager().draw();
  GFXEndScene();
}

int shiftup(int);
static void nav_keyboard_cb( unsigned int  ch,unsigned int mod, bool release, int x, int y ) {
  if (!release)
    nav_keyboard_queue.push_back (((WSK_MOD_LSHIFT==(mod&WSK_MOD_LSHIFT))||(WSK_MOD_RSHIFT==(mod&WSK_MOD_RSHIFT)))?shiftup(ch):ch);
}

bool NavComputer::toggleVisibility(const EventCommandId& command, Control* control) {
  if(m_visible) {
    m_window->close();
    m_visible = false;
    
    pathman->updatePaths();

    RestoreKB();
    GFXLoop (main_loop);
    RestoreMouse();
      
    GameCockpit::NavScreen(KBData(),PRESS);
      
  }
  else {
    GameCockpit::NavScreen(KBData(),PRESS);
    //Initialize callback functions
    winsys_set_keyboard_func(nav_keyboard_cb);  
    winsys_set_mouse_func(EventManager::ProcessMouseClick);
    winsys_set_motion_func(EventManager::ProcessMouseActive);
    winsys_set_passive_motion_func(EventManager::ProcessMousePassive);
    m_window->open();
    m_visible = true;
    GFXLoop(nav_main_loop);

    // Simulate clicking the leftmost mode button.
    // We don't actually use the button because there isn't a button if there's only one mode.
    processWindowCommand(displayModeInfo[m_displayModes[0]].command, NULL);

  }
  return m_visible;
}

// Redo the title strings for the display.
void NavComputer::recalcTitle() {
  // Generic nav title for the display.
  
  string baseTitle = "Navigational Computer";
  baseTitle += " (";
  baseTitle += displayModeInfo[m_currentDisplay].title;
  baseTitle += ")";    

  // Set the string in the base title control.
  StaticDisplay* baseTitleDisplay = static_cast<StaticDisplay*>( window()->findControlById("NavigationTitle") );
  assert(baseTitleDisplay != NULL);
  baseTitleDisplay->setText(baseTitle);
}

// Create the window and controls for the Options Menu.
void NavComputer::RenameConfirm::init(void) {
  Window* window = new Window;
  setWindow(window);
      
  window->setSizeAndCenter(Size(.9, .62));
  window->setTexture("basecomputer.png");
  window->setColor( GFXColor(0,1,0,.1) );
  window->setOutlineColor( GFXColor(.7,.7,.7) );
  window->setOutlineWidth(2.0);
  window->setController(this);

  // Information.
  StaticDisplay* text = new StaticDisplay;
  text->setRect( Rect(-.4, .11, .8, .15) );
  text->setText("Enter the new name for this path.");
  text->setTextColor(GFXColor(.7,1,.4));
  text->setMultiLine(true);
  text->setColor(GUI_CLEAR);
  text->setFont( Font(.07, 1.25) );
  text->setId("Information");
  // Put it on the window.
  window->addControl(text);

  // Path name input box.
  StaticDisplay* pathNameBox = new TextInputDisplay(&nav_keyboard_queue,"\x1b\n\t\r");
  pathNameBox->setRect( Rect(-.4, -.09, .8, .15) );
  pathNameBox->setColor( GFXColor(0,1,1,.1) );
  pathNameBox->setOutlineColor(GUI_OPAQUE_MEDIUM_GRAY());
  pathNameBox->setFont( Font(.07) );
  pathNameBox->setMultiLine(true);
  pathNameBox->setTextColor(GUI_OPAQUE_WHITE());
  pathNameBox->setTextMargins(Size(.02,.01));
  pathNameBox->setId("PathNameBox");
  window->addControl(pathNameBox);

  // Confirm Button.
  NewButton* confirm = new NewButton;
  confirm->setRect( Rect(.05, -.25, .30, .10) );
  confirm->setLabel("Rename");
  confirm->setCommand("Rename");
  confirm->setColor( GFXColor(1,.5,0,.25) );
  confirm->setTextColor( GUI_OPAQUE_WHITE() );
  confirm->setDownColor( GFXColor(1,.5,0,.6) );
  confirm->setDownTextColor( GUI_OPAQUE_BLACK() );
  confirm->setHighlightColor( GFXColor(0,1,0,.4) );
  confirm->setFont(Font(.08, BOLD_STROKE));
  // Put the button on the window.
  window->addControl(confirm);

  // Resume Game button.
  NewButton* resume = new NewButton;
  resume->setRect( Rect(-.35, -.26, .30, .12) );
  resume->setLabel("Cancel");
  resume->setCommand("Window::Close");
  resume->setColor( GFXColor(0,1,0,.25) );
  resume->setTextColor( GUI_OPAQUE_WHITE() );
  resume->setDownColor( GFXColor(0,1,0,.6) );
  resume->setDownTextColor( GUI_OPAQUE_BLACK() );
  resume->setHighlightColor( GFXColor(0,1,0,.4) );
  resume->setFont(Font(.08, BOLD_STROKE));
  // Put the button on the window.
  window->addControl(resume);

  window->setModal(true);
}

// Process a command event from the Options Menu window.
bool NavComputer::RenameConfirm::processWindowCommand(const EventCommandId& command, Control* control) {
  if(command == "Rename") {
    TextInputDisplay* input = static_cast<TextInputDisplay*>( window()->findControlById("PathNameBox") );
    assert(input != NULL);
    m_parent->actionRenameConfirmed(input->text());
    window()->close();
  } else {
    // Not a command we know about.
    return WindowController::processWindowCommand(command, control);
  }

  return true;
}

// Load the paths to be put in the lister.
void NavComputer::loadPathLister() {
  SimplePicker* listPicker = static_cast<SimplePicker*>( window()->findControlById("PathLister") );
  assert(listPicker != NULL);
  listPicker->clear();
  
  currentPath=NULL;
  for(vector<NavPath *>::iterator i=pathman->paths.begin(); i<pathman-> paths.end(); ++i)
    listPicker->addCell(new ValuedPickerCell<NavPath*>((*i), (*i)->getName()));
  
  // Make sure the description is empty.
  StaticDisplay* desc = static_cast<StaticDisplay*>( window()->findControlById("Description") );
  assert(desc != NULL);
  desc->setText("");
}

// Load the paths to be put in the lister.
void NavComputer::loadChainLister() {
  SimplePicker* chainPicker = static_cast<SimplePicker*>( window()->findControlById("ChainLister") );
  assert(chainPicker != NULL);
  chainPicker->clear();

  for(vector<NavPath *>::iterator i=pathman->paths.begin(); i<pathman-> paths.end(); ++i)
    chainPicker->addCell(new ValuedPickerCell<NavPath*>((*i), (*i)->getName()));    
}

void NavComputer::loadCriteriaPickerCell(SimplePicker* picker, ValuedPickerCell<CriteriaNode*>* parent, CriteriaNode *node) {
  assert(node != NULL);
  ValuedPickerCell<CriteriaNode*>* cell = new ValuedPickerCell<CriteriaNode*>(node, node->getText());
  cell->setHideChildren(false);

  if(parent)
    parent->addChild(cell);
  else {
    assert(picker != NULL);
    picker->addCell(cell);
  }  

  vector<CriteriaNode*> childList = node->getChildren();
  for(vector<CriteriaNode*>::iterator i=childList.begin(); i<childList.end(); ++i)
    loadCriteriaPickerCell(picker, cell, (*i));
}
  

// Load the criteria to be put in the lister.
void NavComputer::loadCriteriaLister() {
  SimplePicker* picker = static_cast<SimplePicker*>( window()->findControlById("CriteriaLister") );
  assert(picker != NULL);
  picker->clear();

  if(criteria)
    if(static_cast<CriteriaPathNode*>(currentNode)->getRoot()->getChild())
      loadCriteriaPickerCell(picker, NULL, static_cast<CriteriaPathNode*>(currentNode)->getRoot()->getChild());
}

// Load the absolute button.
void NavComputer::loadAbsoluteButton() {
  NewButton* absolute = static_cast<NewButton*>( window()->findControlById("Absolute") );
  assert(absolute != NULL);
  absolute->setLabel(navsys->systemIter[navsys->systemselectionindex].GetName());
}

bool NavComputer::setCurrentNode(PathNode * source) {
  if(currentNode)
    delete currentNode;
  currentNode=source;
  updateNodeDescription();
  return true;
}

void NavComputer::updateDescription() {
  StaticDisplay* desc = static_cast<StaticDisplay*>( window()->findControlById("Description") );
  assert(desc != NULL);

  if(currentPath) {
    desc->setText(currentPath->getDescription());
  }
  else {
    desc->setText("");
  }
}

void NavComputer::updateNodeDescription() {
  StaticDisplay* desc = static_cast<StaticDisplay*>( window()->findControlById("NodeDescription") );
  assert(desc != NULL);

  if(currentNode) {
    desc->setText(currentNode->getDescription());
  }
  else {
    desc->setText("");
  }
}

// The selection in the Path lister changed.
bool NavComputer::pathListerChangedSelection(const EventCommandId& command, Control* control) {
  assert(control != NULL);
  Picker* picker = static_cast<Picker*>(control);
  ValuedPickerCell<NavPath*>* cell = static_cast<ValuedPickerCell<NavPath*>*>(picker->selectedCell());

  if(cell == NULL)
    currentPath=NULL;
  else
    currentPath=cell->value();
    
  updateDescription();

  return true;
}

bool NavComputer::actionAdd(const EventCommandId& command, Control* control) {
  pathman->addPath();
  loadPathLister();
  return true;
}

bool NavComputer::actionShowPath(const EventCommandId& command, Control* control) {
  if(currentPath)
    currentPath->setVisible(!currentPath->getVisible());
  updateDescription();
  return true;
}

bool NavComputer::actionRename(const EventCommandId& command, Control* control) {
  if(currentPath) {
    RenameConfirm *renamer= new RenameConfirm(this);
    renamer->init();
    renamer->run();
  }
  return true;
}

bool NavComputer::actionRemove(const EventCommandId& command, Control* control) {  
  if(currentPath)
    pathman->removePath(currentPath);
  loadPathLister();
  return true;
}

bool NavComputer::actionShowAll(const EventCommandId& command, Control* control) {
  pathman->showAll();
  updateDescription();
  return true;
}

bool NavComputer::actionShowNone(const EventCommandId& command, Control* control) {
  pathman->showNone();
  updateDescription();
  return true;
}

bool NavComputer::actionSource(const EventCommandId& command, Control* control) {
  if(currentNode) {
    assert(currentPath);
    currentPath->setSourceNode(currentNode->clone());
    updateDescription();
  }
  return true;
}

bool NavComputer::actionDestination(const EventCommandId& command, Control* control) {
  if(currentNode) {
    assert(currentPath);
    currentPath->setDestinationNode(currentNode->clone());
    updateDescription();
  }
  return true;
}

bool NavComputer::actionCurrent(const EventCommandId& command, Control* control) {
  setCurrentNode(new CurrentPathNode());
  criteria=false;
  return true;
}

bool NavComputer::actionTarget(const EventCommandId& command, Control* control) {
  setCurrentNode(new TargetPathNode());
  criteria=false;
  return true;
}

bool NavComputer::actionAbsolute(const EventCommandId& command, Control* control) {
  setCurrentNode(new AbsolutePathNode(navsys->systemselectionindex));
  criteria=false;
  return true;
}

bool NavComputer::actionAnd(const EventCommandId& command, Control* control) {
  Picker* parameterPicker = static_cast<Picker*>( window()->findControlById("ParameterLister") );
  assert(parameterPicker != NULL);
  
  Picker* criteriaPicker = static_cast<Picker*>( window()->findControlById("CriteriaLister") );
  assert(criteriaPicker != NULL);

  TextInputDisplay* input = static_cast<TextInputDisplay*>( window()->findControlById("ParameterValueBox") );
  assert(input != NULL);
  if(input->text() == "")
    return true;
  
  ValuedPickerCell<CriteriaType>* parameterCell = static_cast<ValuedPickerCell<CriteriaType>*>(parameterPicker->selectedCell());
  ValuedPickerCell<CriteriaNode*>* criteriaCell = static_cast<ValuedPickerCell<CriteriaNode*>*>(criteriaPicker->selectedCell());

  if(parameterCell == NULL)
    return true;

  if(!criteria) {
    setCurrentNode(new CriteriaPathNode());
    criteria=true;
  }
  
  CriteriaNode *newNode;
  if(parameterCell->value()==CONTAINS)
    newNode=new CriteriaContains(input->text());
  else if(parameterCell->value()==OWNEDBY)
    newNode=new CriteriaOwnedBy(input->text());
  else
    newNode=new CriteriaSector(input->text());
  
  if(static_cast<CriteriaPathNode*>(currentNode)->getRoot()->getChild() == NULL) {
    static_cast<CriteriaPathNode*>(currentNode)->getRoot()->setChild(newNode);
  }
  else {
    if(criteriaCell == NULL)
      return true;
    
    new CriteriaAnd(criteriaCell->value(), newNode);
  }
  updateNodeDescription();
  loadCriteriaLister();
  return true;
}

bool NavComputer::actionOr(const EventCommandId& command, Control* control) {
  Picker* parameterPicker = static_cast<Picker*>( window()->findControlById("ParameterLister") );
  assert(parameterPicker != NULL);
  
  Picker* criteriaPicker = static_cast<Picker*>( window()->findControlById("CriteriaLister") );
  assert(criteriaPicker != NULL);

  TextInputDisplay* input = static_cast<TextInputDisplay*>( window()->findControlById("ParameterValueBox") );
  assert(input != NULL);
  if(input->text() == "")
    return true;
  
  ValuedPickerCell<CriteriaType>* parameterCell = static_cast<ValuedPickerCell<CriteriaType>*>(parameterPicker->selectedCell());
  ValuedPickerCell<CriteriaNode*>* criteriaCell = static_cast<ValuedPickerCell<CriteriaNode*>*>(criteriaPicker->selectedCell());

  if(parameterCell == NULL)
    return true;

  if(!criteria) {
    setCurrentNode(new CriteriaPathNode());
    criteria=true;
  }
  
  CriteriaNode *newNode;
  if(parameterCell->value()==CONTAINS)
    newNode=new CriteriaContains(input->text());
  else if(parameterCell->value()==OWNEDBY)
    newNode=new CriteriaOwnedBy(input->text());
  else
    newNode=new CriteriaSector(input->text());
  
  if(static_cast<CriteriaPathNode*>(currentNode)->getRoot()->getChild() == NULL) {
    static_cast<CriteriaPathNode*>(currentNode)->getRoot()->setChild(newNode);
  }
  else {
    if(criteriaCell == NULL)
      return true;
    
    new CriteriaOr(criteriaCell->value(), newNode);
  }

  updateNodeDescription();
  loadCriteriaLister();
  return true;
}

bool NavComputer::actionNot(const EventCommandId& command, Control* control) {
  Picker* criteriaPicker = static_cast<Picker*>( window()->findControlById("CriteriaLister") );
  assert(criteriaPicker != NULL);
  ValuedPickerCell<CriteriaNode*>* criteriaCell = static_cast<ValuedPickerCell<CriteriaNode*>*>(criteriaPicker->selectedCell());

  if(criteriaCell == NULL)
    return true;

  assert(criteriaCell->value() != NULL);
  new CriteriaNot(criteriaCell->value());

  updateNodeDescription();
  loadCriteriaLister();
  return true;
}

bool NavComputer::actionRemoveCriteria(const EventCommandId& command, Control* control) {
  Picker* criteriaPicker = static_cast<Picker*>( window()->findControlById("CriteriaLister") );
  assert(criteriaPicker != NULL);
  ValuedPickerCell<CriteriaNode*>* criteriaCell = static_cast<ValuedPickerCell<CriteriaNode*>*>(criteriaPicker->selectedCell());

  if(criteriaCell == NULL)
    return true;

  CriteriaNode *deleteHere = criteriaCell->value()->unhook();
  if(deleteHere)
    delete deleteHere;

  updateNodeDescription();
  loadCriteriaLister();
  return true;
}

bool NavComputer::actionChain(const EventCommandId& command, Control* control) {
  Picker* pathPicker = static_cast<Picker*>( window()->findControlById("ChainLister") );
  assert(pathPicker != NULL);

  Picker* typePicker = static_cast<Picker*>( window()->findControlById("ChainTypeLister") );
  assert(typePicker != NULL);

  ValuedPickerCell<NavPath*>* pathCell = static_cast<ValuedPickerCell<NavPath*>*>(pathPicker->selectedCell());
  ValuedPickerCell<ChainPathNode::PartType>* typeCell = static_cast<ValuedPickerCell<ChainPathNode::PartType>*>(typePicker->selectedCell());

  if(!pathCell || !typeCell)
    return true;

  setCurrentNode(new ChainPathNode(pathCell->value(), typeCell->value()));
  criteria=false;
  return true;
}
 
void NavComputer::actionRenameConfirmed(std::string name) {
  assert(currentPath != NULL);
  
  currentPath->setName(name);
  loadPathLister();
}

Generated by  Doxygen 1.6.0   Back to index