/*
 * This file is part of Ginkgo CADx
 *
 * Copyright (c) 2015-2016 Gert Wollny
 * Copyright (c) 2008-2014 MetaEmotion S.L. All rights reserved.
 *
 * Ginkgo CADx 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; version 3.
 *
 * 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser Public License
 * along with Ginkgo CADx; if not, see <http://www.gnu.org/licenses/>.
 *
 */


#include "wxginkgotoolbar.h"

#include <wx/dcbuffer.h>
#include <wx/menu.h>
#include <wx/aui/aui.h>

enum {
        wxITEM_CONTROL = wxITEM_MAX,
        wxITEM_LABEL,
        wxITEM_SPACER
};

const int BUTTON_DROPDOWN_WIDTH = 10;

class ToolbarCommandCapture : public wxEvtHandler
{
public:

        ToolbarCommandCapture()
        {
                m_lastId = 0;
        }
        int GetCommandId() const
        {
                return m_lastId;
        }

        bool ProcessEvent(wxEvent& evt)
        {
                if (evt.GetEventType() == wxEVT_MENU) {
                        m_lastId = evt.GetId();
                        return true;
                }

                if (GetNextHandler())
                        return GetNextHandler()->ProcessEvent(evt);

                return false;
        }

private:
        int m_lastId;
};

wxGinkgoToolBarArt::wxGinkgoToolBarArt()
{
}

wxGinkgoToolBarArt::wxGinkgoToolBarArt(const wxColor& color)
{
        m_baseColour = color;
}

wxGinkgoToolBarArt::~wxGinkgoToolBarArt()
{
}

void wxGinkgoToolBarArt::SetCustomBaseColor(const wxColor& color)
{
        m_baseColour = color;
}

wxColor wxGinkgoToolBarArt::GetCustomBaseColor()
{
        return m_baseColour;
}

int wxGinkgoToolBarArt::ShowDropDown(wxWindow* wnd, const wxAuiToolBarItemArray& items)
{
        wxMenu menuPopup;

        size_t items_added = 0;

        size_t i, count = items.GetCount();
        for (i = 0; i < count; ++i) {
                wxAuiToolBarItem& item = items.Item(i);

                if (item.GetKind() == wxITEM_NORMAL) {
                        wxString text = item.GetShortHelp();
                        if (text.empty())
                                text = item.GetLabel();

                        if (text.empty())
                                text = wxT(" ");

                        wxMenuItem* m =  new wxMenuItem(&menuPopup, item.GetId(), text, item.GetShortHelp());

                        m->SetBitmap(item.GetBitmap());
                        menuPopup.Append(m);
                        items_added++;
                } else if (item.GetKind() == wxITEM_SEPARATOR) {
                        if (items_added > 0)
                                menuPopup.AppendSeparator();
                }
        }

        // find out where to put the popup menu of window items
        wxPoint pt = ::wxGetMousePosition();
        pt = wnd->ScreenToClient(pt);

        // find out the screen coordinate at the bottom of the tab ctrl
        wxRect cli_rect = wnd->GetClientRect();
        pt.y = cli_rect.y + cli_rect.height;

        ToolbarCommandCapture* cc = new ToolbarCommandCapture;
        wnd->PushEventHandler(cc);
        wnd->PopupMenu(&menuPopup, pt);
        int command = cc->GetCommandId();
        wnd->PopEventHandler(true);

        return command;
}

void wxGinkgoToolBarArt::DrawDropDownButton(
        wxDC& dc,
        wxWindow* /*wnd*/,
        const wxAuiToolBarItem& item,
        const wxRect& rect)
{
        const int BUTTON_DROPDOWN_WIDTH = 10;
        static const unsigned char DISABLED_TEXT_GREY_HUE = wxColour::AlphaBlend(0, 255, 0.4);
        const wxColour DISABLED_TEXT_COLOR(DISABLED_TEXT_GREY_HUE, DISABLED_TEXT_GREY_HUE, DISABLED_TEXT_GREY_HUE);

        int textWidth = 0, textHeight = 0, textX = 0, textY = 0;
        int bmpX = 0, bmpY = 0, dropBmpX = 0, dropBmpY = 0;

        wxRect buttonRect = wxRect(rect.x,
                                   rect.y,
                                   rect.width-BUTTON_DROPDOWN_WIDTH,
                                   rect.height);
        wxRect dropDownRect = wxRect(rect.x+rect.width-BUTTON_DROPDOWN_WIDTH-1,
                                     rect.y,
                                     BUTTON_DROPDOWN_WIDTH+1,
                                     rect.height);

        if (m_flags & wxAUI_TB_TEXT) {
                dc.SetFont(m_font);

                int tx, ty;
                if (m_flags & wxAUI_TB_TEXT) {
                        dc.GetTextExtent(wxT("ABCDHgj"), &tx, &textHeight);
                        textWidth = 0;
                }

                dc.GetTextExtent(item.GetLabel(), &textWidth, &ty);
        }

        dropBmpX = dropDownRect.x +
                   (dropDownRect.width/2) -
                   (m_buttonDropDownBmp.GetWidth()/2);
        dropBmpY = dropDownRect.y +
                   (dropDownRect.height/2) -
                   (m_buttonDropDownBmp.GetHeight()/2);

        if (m_textOrientation == wxAUI_TBTOOL_TEXT_BOTTOM) {
                bmpX = buttonRect.x +
                       (buttonRect.width/2) -
                       (item.GetBitmap().GetWidth()/2);
                bmpY = buttonRect.y +
                       ((buttonRect.height-textHeight)/2) -
                       (item.GetBitmap().GetHeight()/2);

                textX = rect.x + (rect.width/2) - (textWidth/2) + 1;
                textY = rect.y + rect.height - textHeight - 1;
        } else if (m_textOrientation == wxAUI_TBTOOL_TEXT_RIGHT) {
                bmpX = rect.x + 3;

                bmpY = rect.y +
                       (rect.height/2) -
                       (item.GetBitmap().GetHeight()/2);

                textX = bmpX + 3 + item.GetBitmap().GetWidth();
                textY = rect.y +
                        (rect.height/2) -
                        (textHeight/2);
        }


        if (item.GetState() & wxAUI_BUTTON_STATE_PRESSED) {
                dc.SetPen(wxPen(m_highlightColour));
                dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(140)));
                dc.DrawRectangle(buttonRect);

                dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(170)));
                dc.DrawRectangle(dropDownRect);
        } else if (item.GetState() & wxAUI_BUTTON_STATE_HOVER ||
                   item.IsSticky()) {
                dc.SetPen(wxPen(m_highlightColour));
                dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(170)));
                dc.DrawRectangle(buttonRect);
                dc.DrawRectangle(dropDownRect);
        } else if (item.GetState() & wxAUI_BUTTON_STATE_CHECKED) {
                // Notice that this branch must come after the hover one to ensure the
                // correct appearance when the mouse hovers over a checked item.m_
                dc.SetPen(wxPen(m_highlightColour));
                dc.SetBrush(wxBrush(m_highlightColour.ChangeLightness(170)));
                dc.DrawRectangle(buttonRect);
                dc.DrawRectangle(dropDownRect);
        }

        wxBitmap bmp;
        wxBitmap dropbmp;
        if (item.GetState() & wxAUI_BUTTON_STATE_DISABLED) {
                bmp = item.GetDisabledBitmap();
                dropbmp = m_disabledButtonDropDownBmp;
        } else {
                bmp = item.GetBitmap();
                dropbmp = m_buttonDropDownBmp;
        }

        if (!bmp.IsOk())
                return;

        dc.DrawBitmap(bmp, bmpX, bmpY, true);
        dc.DrawBitmap(dropbmp, dropBmpX, dropBmpY, true);

        // set the item's text color based on if it is disabled
        dc.SetTextForeground(*wxBLACK);
        if (item.GetState() & wxAUI_BUTTON_STATE_DISABLED)
                dc.SetTextForeground(DISABLED_TEXT_COLOR);

        if ( (m_flags & wxAUI_TB_TEXT) && !item.GetLabel().empty() ) {
                dc.DrawText(item.GetLabel(), textX, textY);
        }
}

void wxGinkgoToolBarArt::DrawButton(
        wxDC& dc,
        wxWindow* wnd,
        const wxAuiToolBarItem& item,
        const wxRect& rect)
{
        if (item.HasDropDown()) {
                //we have modified default draw function to draw checked + drop down (not supported in wxWidgets)
                DrawDropDownButton(dc, wnd, item, rect);
        } else {
                wxAuiDefaultToolBarArt::DrawButton(dc, wnd, item, rect);
        }
}

//==================================================================================

wxGinkgoToolBar::wxGinkgoToolBar(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) : wxAuiToolBar(parent, id, pos, size, style)
{
        SetToolBitmapSize(wxSize(16,16));
        wxAuiDefaultToolBarArt* pToolArt= new wxGinkgoToolBarArt();
        SetArtProvider(pToolArt);

        Connect(wxEVT_PAINT, wxPaintEventHandler(wxGinkgoToolBar::OnPaint), NULL, this);
        Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(wxGinkgoToolBar::OnLeftDown), NULL, this);
        Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(wxGinkgoToolBar::OnLeftDown), NULL, this);
        Connect(wxEVT_LEFT_UP, wxMouseEventHandler(wxGinkgoToolBar::OnLeftUp), NULL, this);
        Connect(wxEVT_MOTION, wxMouseEventHandler(wxGinkgoToolBar::OnMotion), NULL, this);
        Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler( wxGinkgoToolBar ::OnEraseBackground ) );
}

wxGinkgoToolBar::wxGinkgoToolBar(wxWindow* pParent, const wxColor& color, int style) : wxAuiToolBar(pParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, style|wxAUI_TB_DEFAULT_STYLE)
{
        SetToolBitmapSize(wxSize(16,16));
        wxAuiDefaultToolBarArt* pToolArt= new wxGinkgoToolBarArt(color);
        SetArtProvider(pToolArt);
        Connect(wxEVT_PAINT, wxPaintEventHandler(wxGinkgoToolBar::OnPaint), NULL, this);
        Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(wxGinkgoToolBar::OnLeftDown), NULL, this);
        Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(wxGinkgoToolBar::OnLeftDown), NULL, this);
        Connect(wxEVT_LEFT_UP, wxMouseEventHandler(wxGinkgoToolBar::OnLeftUp), NULL, this);
        Connect(wxEVT_MOTION, wxMouseEventHandler(wxGinkgoToolBar::OnMotion), NULL, this);
        Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler( wxGinkgoToolBar ::OnEraseBackground ) );
}

wxGinkgoToolBar::wxGinkgoToolBar(wxWindow* pParent, const wxColor& color, wxFont& fontBar) : wxAuiToolBar(pParent,wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_TB_DEFAULT_STYLE)
{
        SetToolBitmapSize(wxSize(16,16));
        wxAuiDefaultToolBarArt* pToolArt= new wxGinkgoToolBarArt(color);
        pToolArt->SetFont(fontBar);
        SetArtProvider(pToolArt);
        Connect(wxEVT_PAINT, wxPaintEventHandler(wxGinkgoToolBar::OnPaint), NULL, this);
        Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(wxGinkgoToolBar::OnLeftDown), NULL, this);
        Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(wxGinkgoToolBar::OnLeftDown), NULL, this);
        Connect(wxEVT_LEFT_UP, wxMouseEventHandler(wxGinkgoToolBar::OnLeftUp), NULL, this);
        Connect(wxEVT_MOTION, wxMouseEventHandler(wxGinkgoToolBar::OnMotion), NULL, this);
        Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler( wxGinkgoToolBar ::OnEraseBackground ) );
}

wxGinkgoToolBar::~wxGinkgoToolBar()
{
        Disconnect(wxEVT_MOTION, wxMouseEventHandler(wxGinkgoToolBar::OnMotion), NULL, this);
        Disconnect(wxEVT_LEFT_UP, wxMouseEventHandler(wxGinkgoToolBar::OnLeftUp), NULL, this);
        Disconnect(wxEVT_LEFT_DOWN, wxMouseEventHandler(wxGinkgoToolBar::OnLeftDown), NULL, this);
        Disconnect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(wxGinkgoToolBar::OnLeftDown), NULL, this);
        Disconnect(wxEVT_PAINT, wxPaintEventHandler(wxGinkgoToolBar::OnPaint), NULL, this);
        Disconnect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler( wxGinkgoToolBar ::OnEraseBackground ) );
}

void wxGinkgoToolBar::ForceToggleTool(int tool_id, bool state)
{
        wxAuiToolBarItem* tool = FindTool(tool_id);

        if (tool) {
                if (tool->GetKind() == wxITEM_RADIO) {
                        int i, idx, count;
                        idx = GetToolIndex(tool_id);
                        count = (int)m_items.GetCount();

                        if (idx >= 0 && idx < count) {
                                for (i = idx + 1; i < count; ++i) {
                                        if (m_items[i].GetKind() != wxITEM_RADIO)
                                                break;
                                        m_items[i].SetState(m_items[i].GetState() & ~wxAUI_BUTTON_STATE_CHECKED);
                                }
                                for (i = idx - 1; i >= 0; i--) {
                                        if (m_items[i].GetKind() != wxITEM_RADIO)
                                                break;
                                        m_items[i].SetState(m_items[i].GetState() & ~wxAUI_BUTTON_STATE_CHECKED);
                                }
                        }

                        tool->SetState(tool->GetState() | wxAUI_BUTTON_STATE_CHECKED);
                } else {
                        if (state == true) {
                                tool->SetState(tool->GetState() | wxAUI_BUTTON_STATE_CHECKED);
                        } else {
                                tool->SetState(tool->GetState() & ~wxAUI_BUTTON_STATE_CHECKED);
                        }
                }
        }
}

bool wxGinkgoToolBar::ForceGetToolToggled(int tool_id) const
{
        wxAuiToolBarItem* tool = FindTool(tool_id);

        if (tool) {
                return (tool->GetState() & wxAUI_BUTTON_STATE_CHECKED) ? true : false;
        }

        return false;
}

void wxGinkgoToolBar::ForceSetToolDropDown(int tool_id, bool dropdown)
{
        wxAuiToolBarItem* item = FindTool(tool_id);
        if (!item)
                return;

        if (item->GetKind() != wxITEM_NORMAL) {
                int kind = item->GetKind(); // Hack
                item->SetKind(wxITEM_NORMAL);
                item->SetHasDropDown(dropdown);
                item->SetKind(kind);
        } else {
                item->SetHasDropDown(dropdown);
        }
}

void wxGinkgoToolBar::ForceSetOrientation(int orientation)
{
        wxAuiToolBar::SetOrientation(orientation);
}

void wxGinkgoToolBar::OnPaint(wxPaintEvent& WXUNUSED(evt))
{
        wxAutoBufferedPaintDC dc(this);
        wxRect cli_rect(wxPoint(0,0), GetClientSize());

        bool horizontal = m_orientation == wxHORIZONTAL;

        if (m_windowStyle & wxAUI_TB_PLAIN_BACKGROUND)
                m_art->DrawPlainBackground(dc, this, cli_rect);
        else
                m_art->DrawBackground(dc, this, cli_rect);

        int gripperSize = m_art->GetElementSize(wxAUI_TBART_GRIPPER_SIZE);
        int dropdown_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE);

        // paint the gripper
        if (gripperSize > 0 && m_gripperSizerItem) {
                wxRect gripper_rect = m_gripperSizerItem->GetRect();
                if (horizontal)
                        gripper_rect.width = gripperSize;
                else
                        gripper_rect.height = gripperSize;
                m_art->DrawGripper(dc, this, gripper_rect);
        }

        // calculated how far we can draw items
        int last_extent;
        if (horizontal)
                last_extent = cli_rect.width;
        else
                last_extent = cli_rect.height;
        if (m_overflowVisible)
                last_extent -= dropdown_size;

        // paint each individual tool
        size_t i, count = m_items.GetCount();
        for (i = 0; i < count; ++i) {
                wxAuiToolBarItem& item = m_items.Item(i);

                if (!item.GetSizerItem())
                        continue;

                wxRect item_rect = item.GetSizerItem()->GetRect();


                if ((horizontal  && item_rect.x + item_rect.width >= last_extent) ||
                    (!horizontal && item_rect.y + item_rect.height >= last_extent)) {
                        break;
                }

                switch ( item.GetKind() ) {
                case wxITEM_CHECK:
                case wxITEM_NORMAL:
                        m_art->DrawButton(dc, this, item, item_rect);
                        break;
                case wxITEM_RADIO:
                        // draw a toggle button
                        m_art->DrawButton(dc, this, item, item_rect);
                        break;

                case wxITEM_SEPARATOR:
                        // draw a separator
                        m_art->DrawSeparator(dc, this, item_rect);
                        break;
                case wxITEM_LABEL:
                        // draw a text label only
                        m_art->DrawLabel(dc, this, item, item_rect);
                        break;

                case wxITEM_CONTROL:
                        // draw the control's label
                        m_art->DrawControlLabel(dc, this, item, item_rect);
                        break;
                }

                // fire a signal to see if the item wants to be custom-rendered
                OnCustomRender(dc, item, item_rect);
        }

        // paint the overflow button
        if (dropdown_size > 0 && m_overflowSizerItem) {
                wxRect dropDownRect = GetOverflowRect();
                m_art->DrawOverflowButton(dc, this, dropDownRect, m_overflowState);
        }
}

void wxGinkgoToolBar::OnLeftDown(wxMouseEvent& evt)
{
        //very important to prevent trap because of capturemouse reentering
        if (HasCapture()) {
                ReleaseMouse();
                return;
        }
        wxRect cli_rect(wxPoint(0,0), GetClientSize());

        if (m_gripperSizerItem) {
                wxRect gripper_rect = m_gripperSizerItem->GetRect();
                if (gripper_rect.Contains(evt.GetX(), evt.GetY())) {
                        // find aui manager
                        wxAuiManager* manager = wxAuiManager::GetManager(this);
                        if (!manager)
                                return;

                        int x_drag_offset = evt.GetX() - gripper_rect.GetX();
                        int y_drag_offset = evt.GetY() - gripper_rect.GetY();

                        // gripper was clicked
                        manager->StartPaneDrag(this, wxPoint(x_drag_offset, y_drag_offset));
                        return;
                }
        }

        if (m_overflowSizerItem) {
                wxRect overflow_rect = GetOverflowRect();

                if (m_art &&
                    m_overflowVisible &&
                    overflow_rect.Contains(evt.m_x, evt.m_y)) {
                        wxAuiToolBarEvent e(wxEVT_AUITOOLBAR_OVERFLOW_CLICK, -1);
                        e.SetEventObject(this);
                        e.SetToolId(-1);
                        e.SetClickPoint(wxPoint(evt.GetX(), evt.GetY()));
                        bool processed = GetEventHandler()->ProcessEvent(e);

                        if (processed) {
                                DoIdleUpdate();
                        } else {
                                size_t i, count;
                                wxAuiToolBarItemArray overflow_items;


                                // add custom overflow prepend items, if any
                                count = m_customOverflowPrepend.GetCount();
                                for (i = 0; i < count; ++i)
                                        overflow_items.Add(m_customOverflowPrepend[i]);

                                // only show items that don't fit in the dropdown
                                count = m_items.GetCount();
                                for (i = 0; i < count; ++i) {
                                        if (!GetToolFitsByIndex(i))
                                                overflow_items.Add(m_items[i]);
                                }

                                // add custom overflow append items, if any
                                count = m_customOverflowAppend.GetCount();
                                for (i = 0; i < count; ++i)
                                        overflow_items.Add(m_customOverflowAppend[i]);

                                int res = m_art->ShowDropDown(this, overflow_items);
                                m_overflowState = 0;
                                Refresh(false);
                                if (res != -1) {
                                        wxCommandEvent event(wxEVT_MENU, res);
                                        event.SetEventObject(this);
                                        GetParent()->GetEventHandler()->ProcessEvent(event);
                                }
                        }

                        return;
                }
        }

        m_dragging = false;
        m_actionPos = wxPoint(evt.GetX(), evt.GetY());
        m_actionItem = FindToolByPosition(evt.GetX(), evt.GetY());

        if (m_actionItem) {
                if (m_actionItem->GetState() & wxAUI_BUTTON_STATE_DISABLED) {
                        m_actionPos = wxPoint(-1,-1);
                        m_actionItem = NULL;
                        return;
                }

                UnsetToolTip();

                // fire the tool dropdown event
                wxAuiToolBarEvent e(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, m_actionItem->GetId());
                e.SetEventObject(this);
                e.SetToolId(m_actionItem->GetId());

                int mouse_x = evt.GetX();
                wxRect rect = m_actionItem->GetSizerItem()->GetRect();
                const bool dropDownHit = m_actionItem->HasDropDown() &&
                                         mouse_x >= (rect.x+rect.width-BUTTON_DROPDOWN_WIDTH-1) &&
                                         mouse_x < (rect.x+rect.width);
                e.SetDropDownClicked(dropDownHit);

                e.SetClickPoint(evt.GetPosition());
                e.SetItemRect(rect);

                // we only set the 'pressed button' state if we hit the actual button
                // and not just the drop-down
                SetPressedItem(dropDownHit ? 0 : m_actionItem);

                if(dropDownHit) {
                        m_actionPos = wxPoint(-1,-1);
                        m_actionItem = NULL;
                }

                if(!GetEventHandler()->ProcessEvent(e) || e.GetSkipped()) {
                        CaptureMouse();
                }

                // Ensure hovered item is really ok, as mouse may have moved during
                //  event processing
                wxPoint cursor_pos_after_evt = ScreenToClient(wxGetMousePosition());
                SetHoverItem(FindToolByPosition(cursor_pos_after_evt.x, cursor_pos_after_evt.y));

                DoIdleUpdate();
        }
}

void wxGinkgoToolBar::OnLeftUp(wxMouseEvent& evt)
{
        //process only if this control has registered capture
        if (!HasCapture())
                return;

        SetPressedItem(NULL);

        wxAuiToolBarItem* hitItem;
        hitItem = FindToolByPosition(evt.GetX(), evt.GetY());
        SetHoverItem(hitItem);

        if (m_dragging) {
                ReleaseMouse();
        } else {
                if (m_actionItem && hitItem == m_actionItem) {
                        UnsetToolTip();

                        wxCommandEvent e(wxEVT_MENU, m_actionItem->GetId());
                        e.SetEventObject(this);

                        if (hitItem->GetKind() == wxITEM_CHECK || hitItem->GetKind() == wxITEM_RADIO) {
                                const bool toggle = !(m_actionItem->GetState() & wxAUI_BUTTON_STATE_CHECKED);

                                ForceToggleTool(m_actionItem->GetId(), toggle);

                                // repaint immediately
                                Refresh(false);
                                Update();

                                e.SetInt(toggle);
                        }

                        // we have to release the mouse *before* sending the event, because
                        // we don't know what a handler might do. It could open up a popup
                        // menu for example and that would make us lose our capture anyway.

                        ReleaseMouse();

                        GetEventHandler()->ProcessEvent(e);

                        // Ensure hovered item is really ok, as mouse may have moved during
                        // event processing
                        wxPoint cursor_pos_after_evt = ScreenToClient(wxGetMousePosition());
                        SetHoverItem(FindToolByPosition(cursor_pos_after_evt.x, cursor_pos_after_evt.y));

                        DoIdleUpdate();
                } else
                        ReleaseMouse();
        }
}
void wxGinkgoToolBar::OnMotion(wxMouseEvent& evt)
{
        const bool button_pressed = HasCapture();

        // start a drag event
        if (m_actionItem && !m_dragging && button_pressed &&
            abs(evt.GetX() - m_actionPos.x) + abs(evt.GetY() - m_actionPos.y) > 5) {
                // TODO: sending this event only makes sense if there is an 'END_DRAG'
                // event sent sometime in the future (see OnLeftUp())
                wxAuiToolBarEvent e(wxEVT_AUITOOLBAR_BEGIN_DRAG, GetId());
                e.SetEventObject(this);
                e.SetToolId(m_actionItem->GetId());

                m_dragging = GetEventHandler()->ProcessEvent(e) && !e.GetSkipped();

                DoIdleUpdate();
        }

        if(m_dragging)
                return;

        wxAuiToolBarItem* hitItem = FindToolByPosition(evt.GetX(), evt.GetY());
        if(button_pressed) {
                // if we have a button pressed we want it to be shown in 'depressed'
                // state unless we move the mouse outside the button, then we want it
                // to show as just 'highlighted'
                if (hitItem == m_actionItem)
                        SetPressedItem(m_actionItem);
                else {
                        SetPressedItem(NULL);
                        SetHoverItem(m_actionItem);
                }
        } else {
                SetHoverItem(hitItem);

                // tooltips handling
                wxAuiToolBarItem* packingHitItem;
                packingHitItem = FindToolByPositionWithPacking(evt.GetX(), evt.GetY());
                if (packingHitItem) {
                        if (packingHitItem != m_tipItem) {
                                m_tipItem = packingHitItem;

                                if ( !packingHitItem->GetShortHelp().empty() )
                                        SetToolTip(packingHitItem->GetShortHelp());
                                else
                                        UnsetToolTip();
                        }
                } else {
                        UnsetToolTip();
                        m_tipItem = NULL;
                }

                // figure out the dropdown button state (are we hovering or pressing it?)
                RefreshOverflowState();
        }
}

void wxGinkgoToolBar::OnEraseBackground( wxEraseEvent& event )
{
        event.Skip(false);
}
