/*
 * menu_func.cc
 *
 * Copyright (C) 1995-2001 Kenichi Kourai
 *
 * 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, 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 qvwm; see the file COPYING.  If not, write to
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "main.h"
#include "menu.h"
#include "function.h"
#include "util.h"

void Menu::ExecFunction(FuncNumber fn, int i)
{
  QvFunction::execFunction(fn, this, i);
}

void Menu::ExtractChildMenu(int index)
{
  Point ptFrame;
  int gDir;

  if (index < 0 || index >= nitems)
    return;

  // delayed menu creation
  if (next[index] == NULL) {
    ASSERT(childItem[index]);
    next[index] = new Menu(childItem[index], fs, this, qvWm,
			   leftMargin, nameMargin, hiMargin,
			   imgParentFolder, imgParentIcon);
  }

  switch (fDir) {
    /*
     * To right side.
     */
  case RIGHT:
    ptFrame.x = rc.x + rc.width - 7;
    if (ptFrame.x + next[index]->rc.width > rcScreen.width-1) {
      ptFrame.x = rc.x - next[index]->rc.width + MenuFrameWidth;
      fDir = LEFT;
      gDir = GD_LEFT;
    }
    else
      gDir = GD_RIGHT;
    break;

    /*
     * To left side.
     */
  case LEFT:
    ptFrame.x = rc.x - next[index]->rc.width+MenuFrameWidth;
    if (ptFrame.x + next[index]->rc.width < 0) {
      ptFrame.x = rc.x + rc.width - 7;
      fDir = RIGHT;
      gDir = GD_RIGHT;
    }
    else
      gDir = GD_LEFT;
    break;

  default:
    gDir = 0;  // XXX for warning
    ASSERT(False);
  }

  ptFrame.y = rc.y + CalcItemYPos(index) - MenuFrameWidth;
  if (ptFrame.y + next[index]->rc.height > rcScreen.height - 1) {
    ptFrame.y = ptFrame.y + itemHeight - next[index]->rc.height +
      MenuFrameWidth * 2;
    gDir |= GD_UP;
  }
  else
    gDir |= GD_DOWN;

  child = next[index];
  child->SetQvwm(qvWm);
  child->MapMenu(ptFrame.x, ptFrame.y, gDir);
}

void Menu::MoveFocusUp()
{
  int pFocus;

  if (iFocus == -1) {
    iFocus = nitems - 1;
    while (func[iFocus] == Q_SEPARATOR)
      if (--iFocus == -1)
	return;
  }
  else {
    ASSERT(iFocus >= 0 && iFocus < nitems);
    pFocus = iFocus;

    do {
      if (--iFocus == -1)
	iFocus = nitems - 1;
    } while (func[iFocus] == Q_SEPARATOR);

    SetMenuFocus(pFocus);
  }

  ASSERT(iFocus >= 0 && iFocus < nitems);
  SetMenuFocus(iFocus);
}

void Menu::MoveFocusDown()
{
  int pFocus;

  if (iFocus == -1) {
    iFocus = 0;
    while (func[iFocus] == Q_SEPARATOR)
      if (++iFocus == nitems)
	return;
  }
  else {
    ASSERT(iFocus >= 0 && iFocus < nitems);
    pFocus = iFocus;

    do {
      if (++iFocus == nitems)
	iFocus = 0;
    } while (func[iFocus] == Q_SEPARATOR);

    SetMenuFocus(pFocus);
  }

  ASSERT(iFocus >= 0 && iFocus < nitems);
  SetMenuFocus(iFocus);
}

void Menu::MoveFocusRight()
{
  if (fDir == RIGHT) {
    if (iFocus == -1)
      return;
    ASSERT(iFocus >= 0 && iFocus < nitems);
    if (func[iFocus] == Q_DIR) {
      QvFunction::execFunction(Q_DIR, this, iFocus);
      ASSERT(child);
      QvFunction::execFunction(Q_DOWN_FOCUS, child);
    }
  }
  else {
    ASSERT(fDir == LEFT);
    if (parent != NULL)
      UnmapMenu();
  }
}

void Menu::MoveFocusLeft()
{
  if (fDir == LEFT) {
    if (iFocus == -1)
      return;
    ASSERT(iFocus >= 0 && iFocus < nitems);
    if (func[iFocus] == Q_DIR) {
      QvFunction::execFunction(Q_DIR, this, iFocus);
      ASSERT(child);
      QvFunction::execFunction(Q_DOWN_FOCUS, child);
    }
  }
  else {
    ASSERT(fDir == RIGHT);
    if (parent != NULL)
      UnmapMenu();
  }
}

// exec a function of the focused menu item
void Menu::ExecSelectedItem()
{
  int pFocus;

  ASSERT(iFocus >= 0 && iFocus < nitems);

  if (IsSelectable(func[iFocus])) {
    pFocus = iFocus;
    if (func[iFocus] != Q_DIR)
      UnmapAllMenus();
    
    ExecFunction(func[pFocus], pFocus);
  }
}

void Menu::ExecIndexedItem(int index)
{
  ExecCommand(exec[index]);
}


syntax highlighted by Code2HTML, v. 0.9.1