/* 
 * © 2008-2009 Sun Microsystems, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#include "stdafx.h"
#include "wf_view.h"

using namespace MySQL;
using namespace MySQL::Forms;

using namespace Aga::Controls::Tree;

//----------------- ViewImpl ----------------------------------------------------------------------

/**
 * Determines, depending on the type of the given control, if the layout process should use the control's
 * minimum or its preferred size. 
 * This is necessary because there is a discrepancy between what is considered the minimum size for layouting
 * and the same size for Windows controls. The latter is usually just 0. Instead the preferred size comes close
 * to what we need in the layouting process. Unfortunately, some controls just return their current size
 * (even if they are empty) or the size they need to fit their full text (textbox).
 */
bool ViewImpl::use_min_size_for_layout(Control^ control)
{
  TextBox^ text= dynamic_cast<TextBox^>(control);
  bool needsMinSize= (text != nullptr) && (text->Multiline);
  if (!needsMinSize)
  {
    needsMinSize= (control->GetType() == TabControl::typeid) || (control->GetType() == Panel::typeid)
      || (control->GetType() == ComboBox::typeid) || (control->GetType() == TreeViewAdv::typeid)
      || (control->GetType() == ListBox::typeid);
  }

  return needsMinSize;
}

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

/**
 * Removes the given mode from the auto resize settings of the given control.
 */
void ViewImpl::remove_auto_resize(Control^ control, mforms::AutoResizeMode mode)
{
  // Get backend object for the control, which allows to set individual auto resize modes.
  mforms::View* view= ViewImpl::get_backend_control<mforms::View>(control);
  switch (mode)
  {
    case mforms::ResizeBoth:
      view->set_resize_mode(mforms::ResizeNone);
      break;
    case mforms::ResizeHorizontal:
      if (view->get_resize_mode() == mforms::ResizeBoth)
        view->set_resize_mode(mforms::ResizeVertical);
      else
        view->set_resize_mode(mforms::ResizeNone);
      break;
    case mforms::ResizeVertical:
      if (view->get_resize_mode() == mforms::ResizeBoth)
        view->set_resize_mode(mforms::ResizeHorizontal);
      else
        view->set_resize_mode(mforms::ResizeNone);
      break;
  }
}

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

/**
 * Returns the current resize mode set for the associated back end object of control.
 */
mforms::AutoResizeMode ViewImpl::get_auto_resize(Control^ control)
{
  mforms::View* view= ViewImpl::get_backend_control<mforms::View>(control);
  return view->get_resize_mode();
}

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

/**
 * Determines if the given control can be resized in horizontal direction.
 */
bool ViewImpl::can_auto_resize_horizontally(Control^ control)
{
  mforms::View* view= ViewImpl::get_backend_control<mforms::View>(control);
  mforms::AutoResizeMode mode= view->get_resize_mode();

  return (mode == mforms::ResizeHorizontal) || (mode == mforms::ResizeBoth);
}

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

/**
 * Determines if the given control can be resized in vertical direction.
 */
bool ViewImpl::can_auto_resize_vertically(Control^ control)
{
  mforms::View* view= ViewImpl::get_backend_control<mforms::View>(control);
  mforms::AutoResizeMode mode= view->get_resize_mode();

  return (mode == mforms::ResizeVertical) || (mode == mforms::ResizeBoth);
}

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

/**
 * Enables resizing of the control in both directions.
 */
void ViewImpl::set_full_auto_resize(Control^ control)
{
  ViewImpl::get_backend_control<mforms::View>(control)->set_resize_mode(mforms::ResizeBoth);
}

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

/**
 * Sets resize mode whatever the caller specified.
 */
void ViewImpl::set_auto_resize(Control^ control, mforms::AutoResizeMode mode)
{
  ViewImpl::get_backend_control<mforms::View>(control)->set_resize_mode(mode);
}

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

bool ViewImpl::is_layout_dirty(Control^ control)
{
  mforms::View* view= ViewImpl::get_backend_control<mforms::View>(control);
  ViewImpl^ impl= (ViewImpl^) ObjectImpl::FromUnmanaged(view);
  return impl->LayoutDirty;
}

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

void ViewImpl::set_layout_dirty(Control^ control, bool value)
{
  mforms::View* view= ViewImpl::get_backend_control<mforms::View>(control);
  ViewImpl^ impl= (ViewImpl^) ObjectImpl::FromUnmanaged(view);
  impl->LayoutDirty= value;
}

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

void ViewImpl::set_layout_dirty(::mforms::View *self)
{
  ViewImpl^ view= (ViewImpl^)ObjectImpl::FromUnmanaged(self);

  if (view != nullptr)
    view->LayoutDirty = true;
}

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

void ViewImpl::show(::mforms::View *self, bool show)
{
  ViewImpl^ view= (ViewImpl^)ObjectImpl::FromUnmanaged(self);

  if (view != nullptr)
  {
    Control^ control= view->get_control<Control>();
    if (control->Visible != show)
    {
      control->Visible= show;
      self->set_layout_dirty();
    }
  };
}

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

int ViewImpl::get_width(::mforms::View *self)
{
  ViewImpl^ view= (ViewImpl^)ObjectImpl::FromUnmanaged(self);
  if (view != nullptr)
    return view->get_control<Control>()->ClientSize.Width;
  return 0;
}

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

int ViewImpl::get_height(::mforms::View *self)
{
  ViewImpl^ view= (ViewImpl^)ObjectImpl::FromUnmanaged(self);
  if (view != nullptr)
    return view->get_control<Control>()->ClientSize.Height;
  return 0;
}

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

int ViewImpl::get_preferred_width(::mforms::View *self)
{
  ViewImpl^ view= (ViewImpl^)ObjectImpl::FromUnmanaged(self);
  if (view != nullptr)
  {
    return view->get_control<Control>()->PreferredSize.Width;
  }
  return 0;
}

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

int ViewImpl::get_preferred_height(::mforms::View *self)
{
  ViewImpl^ view= (ViewImpl^)ObjectImpl::FromUnmanaged(self);
  if (view != nullptr)
  {
    return view->get_control<Control>()->PreferredSize.Height;
  }
  return 0;
}

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

int ViewImpl::get_x(::mforms::View *self)
{
  ViewImpl^ view= (ViewImpl^)ObjectImpl::FromUnmanaged(self);
  if (view != nullptr)
  {
    return view->get_control<Control>()->Left;
  }
  return 0;
}

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

int ViewImpl::get_y(::mforms::View *self)
{
  ViewImpl^ view= (ViewImpl^)ObjectImpl::FromUnmanaged(self);
  if (view != nullptr)
  {
    return view->get_control<Control>()->Top;
  }
  return 0;
}

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

void ViewImpl::set_size(::mforms::View *self, int w, int h)
{
  ViewImpl^ view= (ViewImpl^)ObjectImpl::FromUnmanaged(self);
  if (view != nullptr)
  {
    view->LayoutDirty= true;
    view->set_size(w, h);
  }
}

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

void ViewImpl::set_position(::mforms::View *self, int x, int y)
{
  ViewImpl^ view= (ViewImpl^)ObjectImpl::FromUnmanaged(self);
  if (view != nullptr)
  {
    view->LayoutDirty= true; // Actually the parent's layout is now changed, but it is easier so.
    view->set_position(x, y);
  }
}

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

ViewImpl^ ViewImpl::get_parent()
{
  mforms::View* view= get_backend_control<mforms::View>(inner);
  if (view != NULL && view->get_parent() != NULL)
    return (ViewImpl^) ObjectImpl::FromUnmanaged(view->get_parent());

  return nullptr;
}

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

void ViewImpl::relayout()
{
  get_control<Control>()->PerformLayout();
}

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

void ViewImpl::set_enabled(::mforms::View *self, bool flag)
{
  ViewImpl^ view= (ViewImpl^)ObjectImpl::FromUnmanaged(self);
  if (view != nullptr)
    view->get_control<Control>()->Enabled= flag;
}

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

View *ViewImpl::find_subview(::mforms::View *self, std::string &name)
{
  return 0;
}

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

void ViewImpl::set_name(::mforms::View *self, const std::string& text)
{
  ViewImpl^ view= (ViewImpl^)ObjectImpl::FromUnmanaged(self);
  if (view != nullptr)
    view->get_control<Control>()->Name = CppStringToNative(text);
}

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

void ViewImpl::relayout(::mforms::View *self)
{
  ViewImpl^ view= (ViewImpl^)ObjectImpl::FromUnmanaged(self);
  if (view != nullptr)
    view->relayout();
}

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

void ViewImpl::set_tooltip(::mforms::View *self, const std::string& text)
{
  ViewImpl^ view= (ViewImpl^)ObjectImpl::FromUnmanaged(self);
  if (view != nullptr)
    view->set_tooltip(text);
}

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

bool ViewImpl::is_shown(::mforms::View *self)
{
  ViewImpl^ view= (ViewImpl^)ObjectImpl::FromUnmanaged(self);
  if (view != nullptr)
    return view->get_control<Control>()->Visible;
  return false;
}

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

void ViewImpl::set_size(int width, int height)
{
  Control^ control= get_control<Control>();
  if (width < 0)
    width= control->PreferredSize.Width;
  else
    remove_auto_resize(control, ::mforms::ResizeHorizontal);
  if (height < 0)
    height= control->PreferredSize.Height;
  else
    remove_auto_resize(control, ::mforms::ResizeVertical);
  Size newSize = Size(width, height);
  if (!control->Size.Equals(newSize))
  {
    control->Size = newSize;
    control->MinimumSize = newSize;
  }
}

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

void ViewImpl::set_position(int x, int y)
{
  get_control<Control>()->Location = Point(x, y);
}

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

void ViewImpl::set_tooltip(const std::string& text)
{
  if (tooltip == nullptr)
    tooltip= gcnew ToolTip();
  tooltip->SetToolTip(get_control<Control>(), CppStringToNative(text));
}

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

