// $Id: menuitem.h,v 1.29 2018/01/03 21:33:01 mkkuhner Exp $

/*
Copyright 2002-2005 Mary K. Kuhner, Peter Beerli, and Joseph Felsenstein

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

/* Authors: Peter Beerli, Mary Kuhner, Jon Yamato and Joseph Felsenstein */


// Menuitem.h
// is line in the menu and consists of a (key, text, handlerobject)
//
// Peter Beerli

#ifndef MENUITEM_H
#define MENUITEM_H

#include <string>
#include <vector>
#include "menu_strings.h"
#include "menutypedefs.h"
#include "ui_id.h"

class Display;
class MenuInteraction;

// a self-contained unit of display/action invocation in the menu.
// Examples include
//      * a table of values to display
//      * a single menu line that performs an action when its key is entered
//      * a set of similar menu lines that perform the same type of
//          action on different instances of a similar object
class MenuDisplayQuanta
{
  public:
    MenuDisplayQuanta() {};
    virtual ~MenuDisplayQuanta() {};
    virtual void DisplayItemOn(Display & display) = 0;
};

// this ordered set of MenuDisplayQuanta forms the basic
// display unit of a Menu
////////typedef vector<MenuDisplayQuanta*> MenuDisplayQuantaVec;
class MenuDisplayQuantaVec : public std::vector<MenuDisplayQuanta*>
{
  public:
    MenuDisplayQuantaVec() {};
    virtual ~MenuDisplayQuantaVec() {};
    virtual void NukeContents();
};

class MenuDisplayQuantaWithHandler : public MenuDisplayQuanta
{
  public:
    MenuDisplayQuantaWithHandler() {};
    virtual ~MenuDisplayQuantaWithHandler() {};
    //
    virtual bool Handles(std::string inputKey) = 0;
    virtual MenuInteraction_ptr GetHandler(std::string);
    virtual bool HasMultiLineItems() = 0;
};

// like group, but only ever has a single line
class MenuDisplayLine : public MenuDisplayQuantaWithHandler
{
  protected:
    UIId& GetId();
  public:
    MenuDisplayLine() {};
    virtual ~MenuDisplayLine() {};
    // single alphanumeric to invoke this line
    virtual std::string GetKey() = 0;
    // description of this item
    virtual std::string GetText() = 0;
    // current value of this item if any
    virtual std::string GetVariableText() = 0;
    virtual bool IsVisible();
    // has this item been set to a legal value;
    virtual bool IsConsistent();
    // not virtual because I'm assuming all inheritors should
    // use the canned routine given in class Display
    void DisplayItemOn(Display & display);

    // stuff for multi-line items
    virtual bool HasMultiLineItems() { return false; };
    virtual std::vector<std::string> GetExtraText() {return std::vector<std::string>();};
    virtual std::vector<std::string> GetExtraVariableText() {return std::vector<std::string>();};
};

// a set of similar menu lines that perform the same type of
// action on different instances of a similar object
class MenuDisplayGroup : public MenuDisplayQuantaWithHandler
{
  public:
    MenuDisplayGroup() {};
    virtual ~MenuDisplayGroup() {};
    //
    virtual std::vector<UIId> GetVisibleIds() = 0;
    virtual std::vector<UIId> GetInconsistentIds();
    // single alphanumeric to invoke this line
    virtual std::string GetKey(UIId id) = 0;
    // description of this item
    virtual std::string GetText(UIId id) = 0;
    // current value of this item if any
    virtual std::string GetVariableText(UIId id) = 0;
    // not virtual because I'm assuming all inheritors should
    // use the canned routine given in class Display
    void DisplayItemOn(Display & display);
    virtual std::string GetGroupDescription() {return "\n";};
    virtual std::string GetEmptyDescription() {return "\n";};

    // stuff for multi-line items
    virtual bool HasMultiLineItems() {return false;};
    virtual std::vector<std::string> GetExtraText(UIId) {return std::vector<std::string>();};
    virtual std::vector<std::string> GetExtraVariableText(UIId) {return std::vector<std::string>();};
};

// a several-line unit for display in a menu, not having any associated
// actions that can be invoked from it
class MenuDisplayTable : public MenuDisplayQuanta
{
  public:
    MenuDisplayTable() {};
    virtual ~MenuDisplayTable() {};
    virtual bool IsVisible() = 0;
    virtual std::string CreateDisplayString() = 0;
    // not virtual because I'm assuming all inheritors should
    // use the canned routine given in class Display
    void DisplayItemOn(Display & display);
};

class DisplayOnlyGroupWrapper : public MenuDisplayGroup
{
  protected:
    MenuDisplayGroup * m_group;
  public:
    DisplayOnlyGroupWrapper(MenuDisplayGroup * group);
    virtual ~DisplayOnlyGroupWrapper();
    //
    virtual std::vector<UIId> GetVisibleIds();
    virtual std::vector<UIId> GetInconsistentIds();
    virtual std::string GetKey(UIId id);
    virtual std::string GetText(UIId id);
    virtual std::string GetVariableText(UIId id);
    // void DisplayItemOn(Display & display);
    virtual bool Handles(std::string) { return false;};
};

class KeyedMenuItem : public MenuDisplayLine
{
  protected:
    const std::string key;
  public:
    KeyedMenuItem(const std::string& myKey);
    virtual ~KeyedMenuItem();
    virtual std::string GetKey();
    virtual bool Handles(std::string inputKey);
};

#endif  // MENUITEM_H

//____________________________________________________________________________________
