/* 
 * Copyright (c) 2011, 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_toolbar.h"

#include "base/log.h"
#include "base/string_utilities.h"
#include "ConvUtils.h"

using namespace System::Windows::Forms;
using namespace System::IO;
using namespace System::Drawing;

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

DEFAULT_LOG_DOMAIN(DOMAIN_MFORMS_WRAPPER)

//----------------- MformsToolStripLayout ----------------------------------------------------------

/**
 * Computes the entire layout of the toolstrip (position of items).
 * 
 * @param toolstrip What we are computing the layout for.
 * @param proposedSize The size to start from layouting. Since super ordinated controls may impose
 *                     a layout size we need to honor that (especially important for auto wrapping
 *                     labels).
 * @param preferredSizeOnly If true arrange compute only the minimal size needed, otherwise do a full layout.
 * @return The resulting size of the box.
 */
System::Drawing::Size MformsToolStripLayout::ComputeLayout(MformsToolStrip^ toolstrip,
  System::Drawing::Size proposedSize, bool preferredSizeOnly)
{
  int itemsTotalWidth = 0;
  int maxHeight = 0;
  int expandCount = 0;

  proposedSize.Width -= toolstrip->Padding.Horizontal + toolstrip->GripMargin.Horizontal;
  if (proposedSize.Width < 0)
    proposedSize.Width = 0;

  proposedSize.Height = toolstrip->Size.Height - toolstrip->Padding.Vertical;
  if (proposedSize.Height < 0)
    proposedSize.Height = 0;

  // Determine total width of all items so we can distribute any remaining space over
  // all expander items.
  for each (ToolStripItem^ item in toolstrip->Items)
  {
    if (!item->Visible)
      continue;

    if (item->GetType() != ToolStripSegmentedButton::typeid)
      item->Size = item->GetPreferredSize(proposedSize); // The size includes the item's margin.
    
    if (item->Height > maxHeight)
      maxHeight = item->Height;
    if (item->GetType() == ToolStripExpander::typeid)
      expandCount++; // Expanders have no width per se, but get all that's unused.
    else
      itemsTotalWidth += item->Width;
  }
  
  // Adjust width of the container if it is too small, but don't make the toolbar smaller than
  // the available space. It always stretches over the available space.
  if (proposedSize.Width < itemsTotalWidth)
    proposedSize.Width = itemsTotalWidth;

  // Same for the height.
  if (proposedSize.Height < maxHeight)
    proposedSize.Height = maxHeight;

  if (!preferredSizeOnly)
  {
    // Fraction of remaining space per expander. Due to integral pixel bounds + locations
    // we might end up with a number of unused pixel. These will be individually distributed over
    // all expanders as well.
    int expanderFraction = 0;
    int remainingSpace = 0;
    if (expandCount > 0)
    {
      expanderFraction = (proposedSize.Width - itemsTotalWidth) / expandCount;
      remainingSpace = proposedSize.Width - itemsTotalWidth - (expanderFraction * expandCount);
    }

    int offset = toolstrip->Padding.Left + toolstrip->GripMargin.Horizontal;

    for each (ToolStripItem^ item in toolstrip->Items)
    {
      if (!item->Visible)
        continue;

      if (item->GetType() == ToolStripExpander::typeid)
      {
        offset += expanderFraction;
        if (remainingSpace > 0)
        {
          offset++;
          remainingSpace--;
        }
      }
      else
      {
        System::Drawing::Point itemLocation;

        // Vertically center the item within the bounds of the toolstrip (less its padding).
        itemLocation.Y = toolstrip->Padding.Top + (int) Math::Ceiling((proposedSize.Height - item->Height) / 2.0);
        itemLocation.X = offset;
        toolstrip->ApplyLocation(item, itemLocation);
        offset += item->Width;
      }
    }
  }

  proposedSize.Width += toolstrip->Padding.Horizontal + toolstrip->GripMargin.Horizontal;
  proposedSize.Height += toolstrip->Padding.Vertical;

  return proposedSize;
}

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

bool MformsToolStripLayout::Layout(Object^ container, LayoutEventArgs^ arguments)
{
  MformsToolStrip^ toolstrip = (MformsToolStrip^) container;
  if (!ViewImpl::can_layout(toolstrip, arguments->AffectedProperty))
    return false;

  System::Drawing::Size toolStripSize = ComputeLayout(toolstrip, toolstrip->Size, false);

  // Finally resize container if necessary.
  bool parentLayoutNeeded= !toolstrip->Size.Equals(toolStripSize);
  if (parentLayoutNeeded && toolstrip->AutoSize)
    toolstrip->Size = toolStripSize;

  return parentLayoutNeeded;
}

//----------------- MformsToolStrip ----------------------------------------------------------------

MformsToolStrip::MformsToolStrip()
{
}

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

void MformsToolStrip::ApplyLocation(ToolStripItem^ item, Point location)
{
  // SetItemLocation is protected and its visibility cannot be increased nor is it possible
  // to allow access to it via friend class or using clauses.
  SetItemLocation(item, location);
}

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

System::Drawing::Size MformsToolStrip::GetPreferredSize(System::Drawing::Size proposedSize)
{
  return layoutEngine->ComputeLayout(this, proposedSize, true);
}

//----------------- ToolBarItemImpl ----------------------------------------------------------------

ToolBarItemImpl::ToolBarItemImpl(mforms::ToolBarItem* item)
  : ObjectImpl(item)
{
}

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

ToolBarItemImpl::~ToolBarItemImpl()
{
  delete normalImage;
  delete activeImage;
}

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

void ToolBarItemImpl::UpdateItemImage()
{
  ToolStripItem^ item = get_control<ToolStripItem>();
  ToolStripButton^ button = dynamic_cast<ToolStripButton^>(item);
  bool isChecked = false;
  if (button != nullptr)
    isChecked = dynamic_cast<ToolStripButton^>(item)->Checked;

  static Size borderSize(2, 2);
  if (item->GetType() == ToolStripSegmentedButton::typeid)
  {
    // For segmented buttons we use a trick to avoid the implicit border given by the default
    // implementation. Using a background image avoids it. We have to size the item
    // explicitly, though. Auto size must be off to make this work.
    if (isChecked)
    {
      item->BackgroundImage = activeImage;
      if (activeImage != nullptr)
      {
        item->AutoSize = false;
        item->Size = activeImage->Size + button->Margin.Size + borderSize;
      }
    }
    else
    {
      item->BackgroundImage = normalImage;
      if (normalImage != nullptr)
      {
        item->AutoSize = false;
        item->Size = normalImage->Size + button->Margin.Size + borderSize;
      }
    }
  }
  else
  {
    // Use the normal image also for checked items if no active image exists.
    if (isChecked && activeImage != nullptr)
    {
      item->Image = activeImage;
      item->AutoSize = false;
      item->Size = activeImage->Size + button->Margin.Size + borderSize;
    }
    else
    {
      item->Image = normalImage;
      if (normalImage != nullptr)
      {
        item->AutoSize = false;
        item->Size = normalImage->Size + button->Margin.Size + borderSize;
      }
    }
  }
}

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

void ToolBarItemImpl::set_item_checked(bool state)
{
  ToolStripButton^ button = get_control<ToolStripButton>();
  if (button != nullptr && button->Checked != state)
  {
    button->Checked = state;
    UpdateItemImage();
  }
}

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

void ToolBarItemImpl::OnItemActivation(Object^ sender, System::EventArgs^ e)
{
  ToolStripItem^ native_item = dynamic_cast<ToolStripItem^>(sender);

  if (native_item != nullptr && native_item->Tag != nullptr)
  {
    mforms::ToolBarItem* item = ViewImpl::get_backend_control<mforms::ToolBarItem>(native_item);
    if (item != NULL)
    {
      item->callback();
      UpdateItemImage();
    }
  }
}

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

void ToolBarItemImpl::OnColorItemActivation(Object^ sender, System::EventArgs^ e)
{
  ToolStripButton^ button = dynamic_cast<ToolStripButton^>(sender);
  ToolStripDropDownButton^ dropdown = dynamic_cast<ToolStripDropDownButton^>(button->Tag);
  dropdown->Image = button->Image; // Show what was selected in the button too.
  dropdown->Text = button->Text;

  if (dropdown->Tag != nullptr)
  {
    mforms::ToolBarItem* item = ViewImpl::get_backend_control<mforms::ToolBarItem>(dropdown);
    if (item != NULL)
      item->callback();
  }
}

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

void ToolBarItemImpl::OnKeyPress(Object^ sender, KeyPressEventArgs^ e)
{
  if (e->KeyChar == '\r')
  {
    e->Handled = true;
    ToolStripTextBox^ textField = dynamic_cast<ToolStripTextBox^>(sender);

    if (textField->Tag != nullptr)
    {
      mforms::ToolBarItem* item = ViewImpl::get_backend_control<mforms::ToolBarItem>(textField);

      // XXX: temporary, will later be rewired to search().
      if (item != NULL)
        //item->search(NativeToCppString(textField->Text));
        item->callback();
    }
  }
}

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

void ToolBarItemImpl::focus()
{
  ToolStripItem^ item = get_control<ToolStripItem>();
  ToolStripTextBox^ textbox = dynamic_cast<ToolStripTextBox ^>(item);
  if (textbox != nullptr)
    textbox->Focus();
}

//----------------- ToolBarImpl --------------------------------------------------------------------

ToolBarImpl::ToolBarImpl(mforms::ToolBar* toolbar)
  : ViewImpl(toolbar)
{

}

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

ToolBarImpl::~ToolBarImpl()
{

}

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

bool ToolBarImpl::create_tool_bar(mforms::ToolBar* item, mforms::ToolBarType type)
{
  ToolBarImpl^ toolbar = gcnew ToolBarImpl(item);

  ToolStrip^ native_toolbar = nullptr;
  switch (type)
  {
    case mforms::MainToolBar:
      native_toolbar = ViewImpl::create<MformsToolStrip>(item, toolbar);
      native_toolbar->Name = "MainToolBar";
      native_toolbar->Renderer = gcnew FlatMainToolStripRenderer();
      native_toolbar->Padding = Padding(2);
      native_toolbar->GripMargin = Padding(4, 6, 4, 6);
      native_toolbar->Margin = Padding(4, 5, 2, 5); // Used only for separator items. Does not influence the height.
      native_toolbar->AutoSize = true;
      break;

    case mforms::SecondaryToolBar:
    case mforms::PaletteToolBar:
      native_toolbar = ViewImpl::create<MformsToolStrip>(item, toolbar);
      native_toolbar->Name = "SecondaryToolBar";
      native_toolbar->Renderer = gcnew FlatSubToolStripRenderer();
      native_toolbar->GripStyle = ToolStripGripStyle::Hidden;
      native_toolbar->GripMargin = Padding(2, 4, 2, 5);
      native_toolbar->Padding = Padding(5, 0, 0, 0);
      native_toolbar->AutoSize = false;
      native_toolbar->Size = Size(100, 23);
      try
      {
        native_toolbar->Font = ControlUtilities::GetFont("Microsoft Sans Serif", 8.25f);
      }
      catch (System::ArgumentException^ e)
      {
        // Argument exception pops up when the system cannot find the Regular font style (corrupt font).
        log_error("ToolBarImpl::create_tool_bar failed. %s\n", e->Message);
      }

      native_toolbar->BackColor = Conversions::GetApplicationColor(ApplicationColor::AppColorPanelToolbar, false);
      break;

    case mforms::OptionsToolBar:
      native_toolbar = ViewImpl::create<MformsToolStrip>(item, toolbar);
      native_toolbar->Name = "OptionsToolBar";
      native_toolbar->GripMargin = Padding(4, 6, 4, 6);
      native_toolbar->Margin = Padding(4, 8, 2, 8);
      native_toolbar->RenderMode = ToolStripRenderMode::ManagerRenderMode;
      native_toolbar->AutoSize = true;
      break;

    case mforms::ToolPickerToolBar:
      native_toolbar = ViewImpl::create<ToolStrip>(item, toolbar);
      native_toolbar->Name = "ToolPickerToolBar";
      native_toolbar->BackColor = Conversions::GetApplicationColor(ApplicationColor::AppColorPanelToolbar, false);
      native_toolbar->GripStyle = ToolStripGripStyle::Hidden;
      native_toolbar->LayoutStyle = ToolStripLayoutStyle::VerticalStackWithOverflow;
      native_toolbar->Padding = Padding(0);
      native_toolbar->RenderMode = ToolStripRenderMode::ManagerRenderMode;
      native_toolbar->AutoSize = true;
      break;

    default:
      throw std::runtime_error(base::strfmt("Internal error: unimplemented toolbar type requested (%i).", (int) type));
  }

  return (native_toolbar != nullptr);
}

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

void ToolBarImpl::insert_item(mforms::ToolBar* toolbar, int index, mforms::ToolBarItem* item)
{
  ToolBarImpl^ toolbar_impl = (ToolBarImpl^) ViewImpl::FromUnmanaged(toolbar);
  ToolBarItemImpl^ toolbar_item = (ToolBarItemImpl^) ViewImpl::FromUnmanaged(item);

  if (toolbar_impl != nullptr && toolbar_item != nullptr)
  {
    ToolStrip^ native_toolbar = toolbar_impl->get_control<ToolStrip>();
    ToolStripItem^ native_item = toolbar_item->get_control<ToolStripItem>();

    // update the name of the control, so the accessibility support has something to work with
    native_item->Name = CppStringToNative(item->get_name());
    native_item->AccessibleName = native_item->Name;

    if (index < 0 || index >= native_toolbar->Items->Count)
    {
      index = native_toolbar->Items->Count;
      native_toolbar->Items->Add(native_item);
    }
    else
      native_toolbar->Items->Insert(index, native_item);
  }
}

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

void ToolBarImpl::remove_item(mforms::ToolBar* toolbar, mforms::ToolBarItem* item)
{
  ToolBarImpl^ toolbar_impl = (ToolBarImpl^) ViewImpl::FromUnmanaged(toolbar);
  ToolBarItemImpl^ toolbar_item = (ToolBarItemImpl^) ViewImpl::FromUnmanaged(item);

  if (toolbar_impl != nullptr && toolbar_item != nullptr)
  {
    ToolStrip^ native_toolbar = toolbar_impl->get_control<ToolStrip>();
    ToolStripItem^ native_item = toolbar_item->get_control<ToolStripItem>();
    native_toolbar->Items->Remove(native_item);

    delete native_item;
  }
}

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

bool ToolBarImpl::create_tool_item(mforms::ToolBarItem* item, mforms::ToolBarItemType type)
{
  ToolBarItemImpl^ toolbar_item = gcnew ToolBarItemImpl(item);

  ToolStripItem^ native_item;
  switch (type)
  {
  case mforms::ActionItem:
    native_item = ViewImpl::create<ToolStripButton>(item, toolbar_item, native_item);
    native_item->Click += gcnew System::EventHandler(toolbar_item, &ToolBarItemImpl::OnItemActivation);
    native_item->Margin = Padding(1, 2, 1, 2);
    break;

  case mforms::TextActionItem:
    native_item = ViewImpl::create<ToolStripButton>(item, toolbar_item, native_item);
    native_item->Click += gcnew System::EventHandler(toolbar_item, &ToolBarItemImpl::OnItemActivation); 
    native_item->ForeColor = Conversions::GetApplicationColor(ApplicationColor::AppColorPanelToolbar, true);
    break;

  case mforms::LabelItem:
    native_item = ViewImpl::create<ToolStripLabel>(item, toolbar_item, native_item);
    native_item->ForeColor = Conversions::GetApplicationColor(ApplicationColor::AppColorPanelToolbar, true);
    break;

  case mforms::ToggleItem:
    native_item = ViewImpl::create<ToolStripButton>(item, toolbar_item, native_item);
    native_item->DisplayStyle = ToolStripItemDisplayStyle::Image;
    native_item->Click += gcnew System::EventHandler(toolbar_item, &ToolBarItemImpl::OnItemActivation); 
    native_item->Margin = Padding(1, 2, 1, 2);
    ((ToolStripButton^) native_item)->CheckOnClick = true;
    break;

  case mforms::SegmentedToggleItem:
    native_item = ViewImpl::create<ToolStripSegmentedButton>(item, toolbar_item, native_item);
    native_item->DisplayStyle = ToolStripItemDisplayStyle::Image;
    native_item->Click += gcnew System::EventHandler(toolbar_item, &ToolBarItemImpl::OnItemActivation); 
    native_item->Margin = Padding(0, 0, 0, 0);
    native_item->AutoSize = false;
    ((ToolStripSegmentedButton^) native_item)->CheckOnClick = true;
    break;

  case mforms::SearchFieldItem:
    {
      ToolStripTextBox^ box = ViewImpl::create<ToolStripTextBox>(item, toolbar_item, native_item);
      box->Enabled = true;
      box->AutoSize = false;
      box->Size = Size(180, 20);
      box->TextBox->MaximumSize = Size(180, 20);
      box->KeyPress += gcnew KeyPressEventHandler(toolbar_item, &ToolBarItemImpl::OnKeyPress);

      native_item = box;
      break;
    }

  case mforms::SelectorItem:
    {
      ToolStripComboBox^ selector = ViewImpl::create<ToolStripComboBox>(item, toolbar_item, native_item);
      selector->DropDownStyle = ComboBoxStyle::DropDownList;
      selector->FlatStyle = FlatStyle::Popup;
      selector->Font = ControlUtilities::GetFont("Microsoft Sans Serif", 8.25f);
      selector->Margin = Padding(1, 3, 1, 3);
      selector->SelectedIndexChanged += gcnew EventHandler(toolbar_item, &ToolBarItemImpl::OnItemActivation);
      native_item = selector;
      break;
    }

  case mforms::ColorSelectorItem:
    {
      ToolStripDropDownButton^ selector = ViewImpl::create<ToolStripDropDownButton>(item, toolbar_item, native_item);
      ToolStripDropDown^ dropdown = gcnew ToolStripDropDown();
      selector->DropDown = dropdown;
      selector->DisplayStyle = ToolStripItemDisplayStyle::Image;
      selector->ShowDropDownArrow = true;
      selector->DropDownDirection = ToolStripDropDownDirection::BelowRight;
      selector->AutoSize = false;
      selector->Size = Size(75, 21);
      native_item = selector;

      break;
    }

  case mforms::SeparatorItem:
    native_item = ViewImpl::create<ToolStripSeparator>(item, toolbar_item, native_item);
    break;

  case mforms::ExpanderItem:
    native_item = ViewImpl::create<ToolStripExpander>(item, toolbar_item, native_item);
    break;

  default:
    throw std::runtime_error(base::strfmt("Internal error: unimplemented toolbaritem type requested (%i).", (int) type));
  }

  native_item->ImageScaling = ToolStripItemImageScaling::None;
  native_item->Name = CppStringToNative(item->get_name());

  return true;
}

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

void ToolBarImpl::set_item_icon(mforms::ToolBarItem* item, const std::string& path)
{
  ToolBarItemImpl^ toolbar_item = (ToolBarItemImpl^) ViewImpl::FromUnmanaged(item);
  if (toolbar_item != nullptr)
  {
    String^ iconPath = CppStringToNative(path);
    if (File::Exists(iconPath))
      toolbar_item->NormalImage = Image::FromFile(iconPath);
  }
}

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

void ToolBarImpl::set_item_alt_icon(mforms::ToolBarItem* item, const std::string& path)
{
  ToolBarItemImpl^ toolbar_item = (ToolBarItemImpl^) ViewImpl::FromUnmanaged(item);
  if (toolbar_item != nullptr)
  {
    String^ iconPath = CppStringToNative(path);
    if (File::Exists(iconPath))
      toolbar_item->ActiveImage = Image::FromFile(iconPath);
  }
}

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

void ToolBarImpl::set_item_text(mforms::ToolBarItem* item, const std::string& text)
{
  ToolBarItemImpl^ toolbar_item = (ToolBarItemImpl^) ViewImpl::FromUnmanaged(item);
  if (toolbar_item != nullptr)
  {
    ToolStripItem^ native_item = toolbar_item->get_control<ToolStripItem>();
    String ^native_text = CppStringToNative(text);

    switch (item->get_type())
    {
    case mforms::SelectorItem:
      {
        ToolStripComboBox ^selector = dynamic_cast<ToolStripComboBox^>(native_item);
        int index = selector->FindStringExact(native_text);
        if (index < 0)
          index = 0;
        selector->SelectedIndex = index;
        
        break;
      }
      
    case mforms::ColorSelectorItem:
      {
        // If this item is a color selector then find the entry with the corresponding color
        // and use its image for the selector.
        ToolStripDropDownButton ^selector = dynamic_cast<ToolStripDropDownButton^>(native_item);
        bool found = false;
        for each (ToolStripButton^ button in selector->DropDownItems)
        {
          if (button->Text == native_text)
          {
            native_item->Image = button->Image;
            found = true;
            break;
          }
        }

        if (!found)
          native_item->Image = create_color_image(native_item->Text);

        break;
      }

    default:
      native_item->Text = native_text;
    }
  }
}

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

std::string ToolBarImpl::get_item_text(mforms::ToolBarItem* item)
{
  ToolBarItemImpl^ toolbar_item = (ToolBarItemImpl^) ViewImpl::FromUnmanaged(item);
  if (toolbar_item != nullptr)
    return NativeToCppString(toolbar_item->get_control<ToolStripItem>()->Text);

  return "";
}

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

void ToolBarImpl::set_item_enabled(mforms::ToolBarItem* item, bool state)
{
  ToolBarItemImpl^ toolbar_item = (ToolBarItemImpl^) ViewImpl::FromUnmanaged(item);
  if (toolbar_item != nullptr)
    toolbar_item->get_control<ToolStripItem>()->Enabled = state;
}

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

bool ToolBarImpl::get_item_enabled(mforms::ToolBarItem* item)
{
  ToolBarItemImpl^ toolbar_item = (ToolBarItemImpl^) ViewImpl::FromUnmanaged(item);
  if (toolbar_item != nullptr)
    return toolbar_item->get_control<ToolStripItem>()->Enabled;

  return false;
}

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

void ToolBarImpl::set_item_checked(mforms::ToolBarItem* item, bool state)
{
  ToolBarItemImpl^ toolbar_item = (ToolBarItemImpl^) ViewImpl::FromUnmanaged(item);
  if (toolbar_item != nullptr)
    toolbar_item->set_item_checked(state);
}

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

bool ToolBarImpl::get_item_checked(mforms::ToolBarItem* item)
{
  ToolBarItemImpl^ toolbar_item = (ToolBarItemImpl^) ViewImpl::FromUnmanaged(item);
  if (toolbar_item != nullptr)
  {
    ToolStripButton^ button = toolbar_item->get_control<ToolStripButton>();
    if (button != nullptr)
      return button->Checked;
  }
  return false;
}

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

void ToolBarImpl::set_item_tooltip(mforms::ToolBarItem* item, const std::string& text)
{
  ToolBarItemImpl^ toolbar_item = (ToolBarItemImpl^) ViewImpl::FromUnmanaged(item);
  if (toolbar_item != nullptr)
    toolbar_item->get_control<ToolStripItem>()->ToolTipText = CppStringToNative(text);
}

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

void ToolBarImpl::set_selector_items(mforms::ToolBarItem* item, const std::vector<std::string>& values)
{
  ToolBarItemImpl^ toolbar_item = (ToolBarItemImpl^) ViewImpl::FromUnmanaged(item);
  if (toolbar_item != nullptr)
  {
    switch (item->get_type())
    {
    case mforms::SelectorItem:
      {
        ToolStripComboBox^ combobox = toolbar_item->get_control<ToolStripComboBox>();
        if (combobox != nullptr)
        {
          // Normal combobox.
          List<String^> list = CppStringListToNative(values);
          combobox->Items->AddRange(list.ToArray());
        }
        break;
      }
    case mforms::ColorSelectorItem:
      {
        ToolStripDropDownButton^ selector = toolbar_item->get_control<ToolStripDropDownButton>();
        if (selector != nullptr)
        {
          // Color selector.
          Bitmap^ selected = nullptr;
          List<ToolStripButton^> buttons = gcnew List<ToolStripButton^>();

          for (std::vector<std::string>::const_iterator iterator = values.begin(); iterator != values.end(); iterator++)
          {
            String^ text = CppStringToNative(*iterator);
            ToolStripButton^ button = gcnew ToolStripButton();
            button->DisplayStyle = ToolStripItemDisplayStyle::Image;

            button->Text = text;
            button->Image = create_color_image(text);
            button->Tag = selector;
            button->ImageScaling = ToolStripItemImageScaling::None;
            button->Click += gcnew EventHandler(toolbar_item, &ToolBarItemImpl::OnColorItemActivation);

            buttons.Add(button);
          }
          selector->DropDown->Items->AddRange(buttons.ToArray());

        }
        break;
      }
    }
  }
}

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

Bitmap^ ToolBarImpl::create_color_image(String^ color)
{
  SolidBrush^ brush= gcnew SolidBrush(Color::White);
  Pen^ pen = gcnew Pen(Color::LightGray);

  Bitmap^ image = gcnew Bitmap(60, 15);
  Graphics^ g = Graphics::FromImage(image);
  brush->Color = ColorTranslator::FromHtml(color);
  g->FillRectangle(brush, System::Drawing::Rectangle(1, 0, 58, 14));
  g->DrawRectangle(pen, System::Drawing::Rectangle(1, 0, 58, 14));

  return image;
}

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