/* 
 * Copyright (c) 2010, 2013 Oracle and/or its affiliates. All rights reserved.
 *
 * 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; version 2 of the
 * License.
 * 
 * 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., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#include "stdafx.h"

#include "mforms/mforms.h"
#include "wf_view.h"
#include "wf_menu.h"

#include "ConvUtils.h"

using namespace System::Windows::Forms;

using namespace MySQL::Controls;
using namespace MySQL::Forms;

//----------------- MenuImpl -----------------------------------------------------------------------

MenuImpl::MenuImpl(mforms::Menu *self)
  : ObjectImpl(self)
{
}

//--------------------------------------------------------------------------------------------------

MenuImpl::~MenuImpl()
{
}

//--------------------------------------------------------------------------------------------------

bool MenuImpl::create(mforms::Menu* self)
{
  MenuImpl^ menu = gcnew MenuImpl(self);
  ContextMenuStrip ^strip = ObjectImpl::create<ContextMenuStrip>(self, menu);
  strip->AutoSize = true;
  strip->Opening += gcnew System::ComponentModel::CancelEventHandler(&MenuImpl::MenuOpening);

  switch (base::Color::get_active_scheme())
  {
  case base::ColorSchemeCustom:
  case base::ColorSchemeStandard:
  case base::ColorSchemeStandardWin7:
    {
      TransparentMenuStripRenderer ^renderer = gcnew TransparentMenuStripRenderer();
      strip->Renderer = renderer;
    }
  default:
    {
      Win8MenuStripRenderer ^renderer = gcnew Win8MenuStripRenderer();
      strip->Renderer = renderer;
    }
  }
  return true;
}

//--------------------------------------------------------------------------------------------------

ContextMenuStrip^ MenuImpl::GetNativeControl(mforms::Menu *self)
{
  MenuImpl^ menu= (MenuImpl^) ObjectImpl::FromUnmanaged(self);
  return menu->get_control<ContextMenuStrip>();
}

//--------------------------------------------------------------------------------------------------

void MenuImpl::remove_item(mforms::Menu* self, int i)
{
  MenuImpl^ menu= (MenuImpl^) ObjectImpl::FromUnmanaged(self);
  ContextMenuStrip^ native_menu= menu->get_control<ContextMenuStrip>();
  native_menu->Items->RemoveAt(i);
}

//--------------------------------------------------------------------------------------------------

int MenuImpl::add_item(mforms::Menu* self, const std::string& caption, const std::string& action)
{
  MenuImpl^ menu= (MenuImpl^) ObjectImpl::FromUnmanaged(self);
  ContextMenuStrip^ native_menu= menu->get_control<ContextMenuStrip>();
  ToolStripItem^ item = native_menu->Items->Add(CppStringToNative(caption));
  item->Click += gcnew System::EventHandler(menu, &MenuImpl::ItemClick);
  item->Tag= CppStringToNative(action);

  return native_menu->Items->Count - 1;
}

//--------------------------------------------------------------------------------------------------

int MenuImpl::add_separator(mforms::Menu* self)
{
  MenuImpl^ menu= (MenuImpl^) ObjectImpl::FromUnmanaged(self);
  ContextMenuStrip^ native_menu= menu->get_control<ContextMenuStrip>();

  native_menu->Items->Add(gcnew ToolStripSeparator());
  return native_menu->Items->Count - 1;
}

//--------------------------------------------------------------------------------------------------

int MenuImpl::add_submenu(mforms::Menu* self, const std::string& caption, mforms::Menu* submenu)
{
  MenuImpl^ menu = (MenuImpl^) ObjectImpl::FromUnmanaged(self);
  MenuImpl^ child_menu = (MenuImpl^) ObjectImpl::FromUnmanaged(submenu);

  ContextMenuStrip^ native_menu = menu->get_control<ContextMenuStrip>();
  ToolStripMenuItem^ item = gcnew ToolStripMenuItem(CppStringToNative(caption));
  native_menu->Items->Add(item);
  item->DropDown = child_menu->get_control<ContextMenuStrip>();

  return native_menu->Items->Count - 1;
}

//--------------------------------------------------------------------------------------------------

void MenuImpl::set_item_enabled(mforms::Menu* self, int i, bool flag)
{
  MenuImpl^ menu= (MenuImpl^) ObjectImpl::FromUnmanaged(self);
  ContextMenuStrip^ native_menu= menu->get_control<ContextMenuStrip>();
  native_menu->Items[i]->Enabled= flag;
}

//--------------------------------------------------------------------------------------------------

void MenuImpl::popup_at(mforms::Menu* self, mforms::Object* control, int x, int y)
{
  MenuImpl^ menu= (MenuImpl^) ObjectImpl::FromUnmanaged(self);

  // We need the the .NET control for which to show the context menu.
  Control^ controller = nullptr;
  if (control != NULL)
  {
    ObjectImpl^ wrapper= ObjectImpl::FromUnmanaged(control);
    controller= wrapper->get_control<Control>();
  }
  else
  {
    // If we did not get a control passed in then we take the one under the mouse 
    // determined by the last message position. This should usually work as the context menu
    // is triggered by a right mouse button click.
    DWORD position = GetMessagePos();
    POINT point;
    point.x =  (int)(short) LOWORD(position);
    point.y = (int)(short) HIWORD(position);
    HWND window = WindowFromPoint(point);
    controller = Control::FromHandle(IntPtr(window));
  }

  if (controller != nullptr)
  {
    ContextMenuStrip^ native_menu= menu->get_control<ContextMenuStrip>();
    native_menu->Show(controller, System::Drawing::Point(x, y));
  }
}

//--------------------------------------------------------------------------------------------------

void MySQL::Forms::MenuImpl::clear( mforms::Menu* self )
{
  MenuImpl^ menu= (MenuImpl^) ObjectImpl::FromUnmanaged(self);
  ContextMenuStrip^ native_menu= menu->get_control<ContextMenuStrip>();
  native_menu->Items->Clear();
}

//--------------------------------------------------------------------------------------------------

void MenuImpl::ItemClick(Object^ sender, System::EventArgs^ e)
{
  ToolStripItem^ item = dynamic_cast<ToolStripItem^>(sender);
  if (item != nullptr)
  {
    String^ action = dynamic_cast<String^>(item->Tag);
    if (action != nullptr)
    {
      mforms::Menu* menu = ObjectImpl::get_backend_control<mforms::Menu>(item->Owner);
      if (menu != NULL)
        menu->handle_action(NativeToCppString(action));
    }
  }
}

//--------------------------------------------------------------------------------------------------

void MenuImpl::MenuOpening(Object^ sender, System::ComponentModel::CancelEventArgs^ e)
{
  ContextMenuStrip^ native_menu = dynamic_cast<ContextMenuStrip^>(sender);
  if (native_menu != nullptr)
  {
    mforms::Menu* menu = ObjectImpl::get_backend_control<mforms::Menu>(native_menu);
    if (menu != NULL)
      (*(menu->signal_will_show()))();
  }
}

//--------------------------------------------------------------------------------------------------
