From 1154f91b6a4590d4fda9e4cef75aa4ff35ca57bc Mon Sep 17 00:00:00 2001 From: Benjamin Williams Date: Sun, 24 Aug 2008 09:28:07 +0000 Subject: [PATCH] added wxAuiToolBar git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@55231 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/aui/aui.h | 1 + include/wx/aui/auibar.h | 622 +++++++++ src/aui/auibar.cpp | 2628 ++++++++++++++++++++++++++++++++++++++ src/aui/framemanager.cpp | 20 +- 4 files changed, 3270 insertions(+), 1 deletion(-) create mode 100644 include/wx/aui/auibar.h create mode 100644 src/aui/auibar.cpp diff --git a/include/wx/aui/aui.h b/include/wx/aui/aui.h index b33fc82604..967f6db166 100644 --- a/include/wx/aui/aui.h +++ b/include/wx/aui/aui.h @@ -15,6 +15,7 @@ #include "wx/aui/framemanager.h" #include "wx/aui/dockart.h" #include "wx/aui/floatpane.h" +#include "wx/aui/auibar.h" #include "wx/aui/auibook.h" #include "wx/aui/tabmdi.h" diff --git a/include/wx/aui/auibar.h b/include/wx/aui/auibar.h new file mode 100644 index 0000000000..197fdcab7b --- /dev/null +++ b/include/wx/aui/auibar.h @@ -0,0 +1,622 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/aui/toolbar.h +// Purpose: wxaui: wx advanced user interface - docking window manager +// Author: Benjamin I. Williams +// Modified by: +// Created: 2008-08-04 +// RCS-ID: $Id: framemanager.h 53135 2008-04-12 02:31:04Z VZ $ +// Copyright: (C) Copyright 2005, Kirix Corporation, All Rights Reserved. +// Licence: wxWindows Library Licence, Version 3.1 +/////////////////////////////////////////////////////////////////////////////// + + + +#ifndef _WX_AUIBAR_H_ +#define _WX_AUIBAR_H_ + + +#include "wx/defs.h" + +#if wxUSE_AUI + + +enum wxAuiToolBarStyle +{ + wxAUI_TB_TEXT = 1 << 0, + wxAUI_TB_NO_TOOLTIPS = 1 << 1, + wxAUI_TB_NO_AUTORESIZE = 1 << 2, + wxAUI_TB_GRIPPER = 1 << 3, + wxAUI_TB_OVERFLOW = 1 << 4, + wxAUI_TB_VERTICAL = 1 << 5, + wxAUI_TB_HORZ_TEXT = ((1 << 6) | wxAUI_TB_TEXT), + wxAUI_TB_DEFAULT_STYLE = 0 +}; + +enum wxAuiToolBarArtSetting +{ + wxAUI_TBART_SEPARATOR_SIZE = 0, + wxAUI_TBART_GRIPPER_SIZE = 1, + wxAUI_TBART_OVERFLOW_SIZE = 2 +}; + +enum wxAuiToolBarToolTextOrientation +{ + wxAUI_TBTOOL_TEXT_LEFT = 0, // unused/unimplemented + wxAUI_TBTOOL_TEXT_RIGHT = 1, + wxAUI_TBTOOL_TEXT_TOP = 2, // unused/unimplemented + wxAUI_TBTOOL_TEXT_BOTTOM = 3 +}; + + +// aui toolbar event class + +class WXDLLIMPEXP_AUI wxAuiToolBarEvent : public wxNotifyEvent +{ +public: + wxAuiToolBarEvent(wxEventType command_type = wxEVT_NULL, + int win_id = 0) + : wxNotifyEvent(command_type, win_id) + { + is_dropdown_clicked = false; + click_pt = wxPoint(-1, -1); + rect = wxRect(-1,-1, 0, 0); + tool_id = -1; + } +#ifndef SWIG + wxAuiToolBarEvent(const wxAuiToolBarEvent& c) : wxNotifyEvent(c) + { + is_dropdown_clicked = c.is_dropdown_clicked; + click_pt = c.click_pt; + rect = c.rect; + tool_id = c.tool_id; + } +#endif + wxEvent *Clone() const { return new wxAuiToolBarEvent(*this); } + + bool IsDropDownClicked() const { return is_dropdown_clicked; } + void SetDropDownClicked(bool c) { is_dropdown_clicked = c; } + + wxPoint GetClickPoint() const { return click_pt; } + void SetClickPoint(const wxPoint& p) { click_pt = p; } + + wxRect GetItemRect() const { return rect; } + void SetItemRect(const wxRect& r) { rect = r; } + + int GetToolId() const { return tool_id; } + void SetToolId(int id) { tool_id = id; } + +public: + bool is_dropdown_clicked; + wxPoint click_pt; + wxRect rect; + int tool_id; + +#ifndef SWIG +private: + DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxAuiToolBarEvent) +#endif +}; + + +class WXDLLIMPEXP_AUI wxAuiToolBarItem +{ +public: + + wxAuiToolBarItem() + { + window = NULL; + sizer_item = NULL; + space_pixels = 0; + id = 0; + kind = wxITEM_NORMAL; + state = 0; // normal, enabled + proportion = 0; + active = true; + dropdown = true; + sticky = true; + user_data = 0; + } + + wxAuiToolBarItem(const wxAuiToolBarItem& c) + { + Assign(c); + } + + wxAuiToolBarItem& operator=(const wxAuiToolBarItem& c) + { + Assign(c); + return *this; + } + + void Assign(const wxAuiToolBarItem& c) + { + window = c.window; + label = c.label; + bitmap = c.bitmap; + disabled_bitmap = c.disabled_bitmap; + hover_bitmap = c.hover_bitmap; + short_help = c.short_help; + long_help = c.long_help; + sizer_item = c.sizer_item; + min_size = c.min_size; + space_pixels = c.space_pixels; + id = c.id; + kind = c.kind; + state = c.state; + proportion = c.proportion; + active = c.active; + dropdown = c.dropdown; + sticky = c.sticky; + user_data = c.user_data; + } + +public: + + wxWindow* window; // item's associated window + wxString label; // label displayed on the item + wxBitmap bitmap; // item's bitmap + wxBitmap disabled_bitmap; // item's disabled bitmap + wxBitmap hover_bitmap; // item's hover bitmap + wxString short_help; // short help (for tooltip) + wxString long_help; // long help (for status bar) + wxSizerItem* sizer_item; // sizer item + wxSize min_size; // item's minimum size + int space_pixels; // size of a spacer + int id; // item's id + int kind; // item's kind + int state; // state + int proportion; // proportion + bool active; // true if the item is currently active + bool dropdown; // true if the item has a dropdown button + bool sticky; // overrides button states if true (always active) + long user_data; // user-specified data +}; + +#ifndef SWIG +WX_DECLARE_USER_EXPORTED_OBJARRAY(wxAuiToolBarItem, wxAuiToolBarItemArray, WXDLLIMPEXP_AUI); +#endif + + + + +// tab art class + +class WXDLLIMPEXP_AUI wxAuiToolBarArt +{ +public: + + wxAuiToolBarArt() { } + virtual ~wxAuiToolBarArt() { } + + virtual wxAuiToolBarArt* Clone() = 0; + virtual void SetFlags(unsigned int flags) = 0; + virtual void SetFont(const wxFont& font) = 0; + virtual void SetTextOrientation(int orientation) = 0; + + virtual void DrawBackground( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect) = 0; + + virtual void DrawLabel( + wxDC& dc, + wxWindow* wnd, + const wxAuiToolBarItem& item, + const wxRect& rect) = 0; + + virtual void DrawButton( + wxDC& dc, + wxWindow* wnd, + const wxAuiToolBarItem& item, + const wxRect& rect) = 0; + + virtual void DrawDropDownButton( + wxDC& dc, + wxWindow* wnd, + const wxAuiToolBarItem& item, + const wxRect& rect) = 0; + + virtual void DrawControlLabel( + wxDC& dc, + wxWindow* wnd, + const wxAuiToolBarItem& item, + const wxRect& rect) = 0; + + virtual void DrawSeparator( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect) = 0; + + virtual void DrawGripper( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect) = 0; + + virtual void DrawOverflowButton( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect, + int state) = 0; + + virtual wxSize GetLabelSize( + wxDC& dc, + wxWindow* wnd, + const wxAuiToolBarItem& item) = 0; + + virtual wxSize GetToolSize( + wxDC& dc, + wxWindow* wnd, + const wxAuiToolBarItem& item) = 0; + + virtual int GetElementSize(int element_id) = 0; + virtual void SetElementSize(int element_id, int size) = 0; + + virtual int ShowDropDown( + wxWindow* wnd, + const wxAuiToolBarItemArray& items) = 0; +}; + + + +class WXDLLIMPEXP_AUI wxAuiDefaultToolBarArt : public wxAuiToolBarArt +{ + +public: + + wxAuiDefaultToolBarArt(); + virtual ~wxAuiDefaultToolBarArt(); + + virtual wxAuiToolBarArt* Clone(); + virtual void SetFlags(unsigned int flags); + virtual void SetFont(const wxFont& font); + virtual void SetTextOrientation(int orientation); + + virtual void DrawBackground( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect); + + virtual void DrawLabel( + wxDC& dc, + wxWindow* wnd, + const wxAuiToolBarItem& item, + const wxRect& rect); + + virtual void DrawButton( + wxDC& dc, + wxWindow* wnd, + const wxAuiToolBarItem& item, + const wxRect& rect); + + virtual void DrawDropDownButton( + wxDC& dc, + wxWindow* wnd, + const wxAuiToolBarItem& item, + const wxRect& rect); + + virtual void DrawControlLabel( + wxDC& dc, + wxWindow* wnd, + const wxAuiToolBarItem& item, + const wxRect& rect); + + virtual void DrawSeparator( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect); + + virtual void DrawGripper( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect); + + virtual void DrawOverflowButton( + wxDC& dc, + wxWindow* wnd, + const wxRect& rect, + int state); + + virtual wxSize GetLabelSize( + wxDC& dc, + wxWindow* wnd, + const wxAuiToolBarItem& item); + + virtual wxSize GetToolSize( + wxDC& dc, + wxWindow* wnd, + const wxAuiToolBarItem& item); + + virtual int GetElementSize(int element); + virtual void SetElementSize(int element_id, int size); + + virtual int ShowDropDown(wxWindow* wnd, + const wxAuiToolBarItemArray& items); + +protected: + + wxBitmap m_button_dropdown_bmp; + wxBitmap m_disabled_button_dropdown_bmp; + wxBitmap m_overflow_bmp; + wxBitmap m_disabled_overflow_bmp; + wxColour m_base_colour; + wxColour m_highlight_colour; + wxFont m_font; + unsigned int m_flags; + int m_text_orientation; + + wxPen m_gripper_pen1; + wxPen m_gripper_pen2; + wxPen m_gripper_pen3; + + int m_separator_size; + int m_gripper_size; + int m_overflow_size; +}; + + + + +class WXDLLIMPEXP_AUI wxAuiToolBar : public wxControl +{ +public: + + wxAuiToolBar(wxWindow* parent, + wxWindowID id = -1, + const wxPoint& position = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxAUI_TB_DEFAULT_STYLE); + ~wxAuiToolBar(); + + void SetWindowStyleFlag(long style); + + void SetArtProvider(wxAuiToolBarArt* art); + wxAuiToolBarArt* GetArtProvider() const; + + bool SetFont(const wxFont& font); + + + void AddTool(int tool_id, + const wxString& label, + const wxBitmap& bitmap, + const wxString& short_help_string = wxEmptyString, + wxItemKind kind = wxITEM_NORMAL); + + void AddTool(int tool_id, + const wxString& label, + const wxBitmap& bitmap, + const wxBitmap& disabled_bitmap, + wxItemKind kind, + const wxString& short_help_string, + const wxString& long_help_string, + wxObject* client_data); + + void AddTool(int tool_id, + const wxBitmap& bitmap, + const wxBitmap& disabled_bitmap, + bool toggle = false, + wxObject* client_data = NULL, + const wxString& short_help_string = wxEmptyString, + const wxString& long_help_string = wxEmptyString) + { + AddTool(tool_id, + wxEmptyString, + bitmap, + disabled_bitmap, + toggle ? wxITEM_CHECK : wxITEM_NORMAL, + short_help_string, + long_help_string, + client_data); + } + + void AddLabel(int tool_id, + const wxString& label = wxEmptyString, + const int width = -1); + void AddControl(wxControl* control, + const wxString& label = wxEmptyString); + void AddSeparator(); + void AddSpacer(int pixels); + void AddStretchSpacer(int proportion = 1); + + bool Realize(); + + wxControl* FindControl(int window_id); + wxAuiToolBarItem* FindToolByPosition(wxCoord x, wxCoord y) const; + wxAuiToolBarItem* FindToolByIndex(int idx) const; + wxAuiToolBarItem* FindTool(int tool_id) const; + + void ClearTools() { Clear() ; } + void Clear(); + bool DeleteTool(int tool_id); + bool DeleteByIndex(int tool_id); + + size_t GetToolCount() const; + int GetToolPos(int tool_id) const { return GetToolIndex(tool_id); } + int GetToolIndex(int tool_id) const; + bool GetToolFits(int tool_id) const; + wxRect GetToolRect(int tool_id) const; + bool GetToolFitsByIndex(int tool_id) const; + bool GetToolBarFits() const; + + void SetMargins(const wxSize& size) { SetMargins(size.x, size.x, size.y, size.y); } + void SetMargins(int x, int y) { SetMargins(x, x, y, y); } + void SetMargins(int left, int right, int top, int bottom); + + void SetToolBitmapSize(const wxSize& size); + wxSize GetToolBitmapSize() const; + + bool GetOverflowVisible() const; + void SetOverflowVisible(bool visible); + + bool GetGripperVisible() const; + void SetGripperVisible(bool visible); + + void ToggleTool(int tool_id, bool state); + bool GetToolToggled(int tool_id) const; + + void EnableTool(int tool_id, bool state); + bool GetToolEnabled(int tool_id) const; + + void SetToolDropDown(int tool_id, bool dropdown); + bool GetToolDropDown(int tool_id) const; + + void SetToolBorderPadding(int padding); + int GetToolBorderPadding() const; + + void SetToolTextOrientation(int orientation); + int GetToolTextOrientation() const; + + void SetToolPacking(int packing); + int GetToolPacking() const; + + void SetToolProportion(int tool_id, int proportion); + int GetToolProportion(int tool_id) const; + + void SetToolSeparation(int separation); + int GetToolSeparation() const; + + void SetToolSticky(int tool_id, bool sticky); + bool GetToolSticky(int tool_id) const; + + wxString GetToolLabel(int tool_id) const; + void SetToolLabel(int tool_id, const wxString& label); + + wxBitmap GetToolBitmap(int tool_id) const; + void SetToolBitmap(int tool_id, const wxBitmap& bitmap); + + wxString GetToolShortHelp(int tool_id) const; + void SetToolShortHelp(int tool_id, const wxString& help_string); + + wxString GetToolLongHelp(int tool_id) const; + void SetToolLongHelp(int tool_id, const wxString& help_string); + + void SetCustomOverflowItems(const wxAuiToolBarItemArray& prepend, + const wxAuiToolBarItemArray& append); + +protected: + + virtual void OnCustomRender(wxDC& WXUNUSED(dc), + const wxAuiToolBarItem& WXUNUSED(item), + const wxRect& WXUNUSED(rect)) { } + +protected: + + void DoIdleUpdate(); + void SetOrientation(int orientation); + void SetHoverItem(wxAuiToolBarItem* item); + void SetPressedItem(wxAuiToolBarItem* item); + void RefreshOverflowState(); + + int GetOverflowState() const; + wxRect GetOverflowRect() const; + wxSize GetLabelSize(const wxString& label); + wxAuiToolBarItem* FindToolByPositionWithPacking(wxCoord x, wxCoord y) const; + + void DoSetSize(int x, + int y, + int width, + int height, + int sizeFlags = wxSIZE_AUTO); + +protected: // handlers + + void OnSize(wxSizeEvent& evt); + void OnIdle(wxIdleEvent& evt); + void OnPaint(wxPaintEvent& evt); + void OnEraseBackground(wxEraseEvent& evt); + void OnLeftDown(wxMouseEvent& evt); + void OnLeftUp(wxMouseEvent& evt); + void OnRightDown(wxMouseEvent& evt); + void OnRightUp(wxMouseEvent& evt); + void OnMiddleDown(wxMouseEvent& evt); + void OnMiddleUp(wxMouseEvent& evt); + void OnMotion(wxMouseEvent& evt); + void OnLeaveWindow(wxMouseEvent& evt); + void OnSetCursor(wxSetCursorEvent& evt); + +protected: + + wxAuiToolBarItemArray m_items; // array of toolbar items + wxAuiToolBarArt* m_art; // art provider + wxBoxSizer* m_sizer; // main sizer for toolbar + wxAuiToolBarItem* m_action_item; // item that's being acted upon (pressed) + wxAuiToolBarItem* m_tip_item; // item that has its tooltip shown + wxBitmap m_bitmap; // double-buffer bitmap + wxSizerItem* m_gripper_sizer_item; + wxSizerItem* m_overflow_sizer_item; + wxSize m_absolute_min_size; + wxPoint m_action_pos; // position of left-mouse down + wxAuiToolBarItemArray m_custom_overflow_prepend; + wxAuiToolBarItemArray m_custom_overflow_append; + + int m_button_width; + int m_button_height; + int m_sizer_element_count; + int m_left_padding; + int m_right_padding; + int m_top_padding; + int m_bottom_padding; + int m_tool_packing; + int m_tool_border_padding; + int m_tool_text_orientation; + int m_overflow_state; + bool m_dragging; + bool m_gripper_visible; + bool m_overflow_visible; + long m_style; + + DECLARE_EVENT_TABLE() + DECLARE_CLASS(wxAuiToolBar) +}; + + + + +// wx event machinery + +#ifndef SWIG + +BEGIN_DECLARE_EVENT_TYPES() + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_AUI, wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN, 0) + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_AUI, wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK, 0) + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_AUI, wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, 0) + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_AUI, wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK, 0) + DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_AUI, wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG, 0) +END_DECLARE_EVENT_TYPES() + +typedef void (wxEvtHandler::*wxAuiToolBarEventFunction)(wxAuiToolBarEvent&); + +#define wxAuiToolBarEventHandler(func) \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxAuiToolBarEventFunction, &func) + +#define EVT_AUITOOLBAR_TOOL_DROPDOWN(winid, fn) \ + wx__DECLARE_EVT1(wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN, winid, wxAuiToolBarEventHandler(fn)) +#define EVT_AUITOOLBAR_OVERFLOW_CLICK(winid, fn) \ + wx__DECLARE_EVT1(wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK, winid, wxAuiToolBarEventHandler(fn)) +#define EVT_AUITOOLBAR_RIGHT_CLICK(winid, fn) \ + wx__DECLARE_EVT1(wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, winid, wxAuiToolBarEventHandler(fn)) +#define EVT_AUITOOLBAR_MIDDLE_CLICK(winid, fn) \ + wx__DECLARE_EVT1(wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK, winid, wxAuiToolBarEventHandler(fn)) +#define EVT_AUITOOLBAR_BEGIN_DRAG(winid, fn) \ + wx__DECLARE_EVT1(wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG, winid, wxAuiToolBarEventHandler(fn)) + +#else + +// wxpython/swig event work +%constant wxEventType wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN; +%constant wxEventType wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK; +%constant wxEventType wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK; +%constant wxEventType wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK; +%constant wxEventType wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG; + +%pythoncode { + EVT_AUITOOLBAR_TOOL_DROPDOWN = wx.PyEventBinder( wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN, 1 ) + EVT_AUITOOLBAR_OVERFLOW_CLICK = wx.PyEventBinder( wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK, 1 ) + EVT_AUITOOLBAR_RIGHT_CLICK = wx.PyEventBinder( wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, 1 ) + EVT_AUITOOLBAR_MIDDLE_CLICK = wx.PyEventBinder( wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK, 1 ) + EVT_AUITOOLBAR_BEGIN_DRAG = wx.PyEventBinder( wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG, 1 ) +} +#endif // SWIG + +#endif // wxUSE_AUI +#endif // _WX_AUIBAR_H_ + diff --git a/src/aui/auibar.cpp b/src/aui/auibar.cpp new file mode 100644 index 0000000000..a5f6cdee78 --- /dev/null +++ b/src/aui/auibar.cpp @@ -0,0 +1,2628 @@ +/////////////////////////////////////////////////////////////////////////////// + +// Name: src/aui/dockart.cpp +// Purpose: wxaui: wx advanced user interface - docking window manager +// Author: Benjamin I. Williams +// Modified by: +// Created: 2005-05-17 +// RCS-ID: $Id: dockart.cpp 48848 2007-09-21 10:19:53Z SC $ +// Copyright: (C) Copyright 2005-2006, Kirix Corporation, All Rights Reserved +// Licence: wxWindows Library Licence, Version 3.1 +/////////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#if wxUSE_AUI + +#include "wx/statline.h" +#include "wx/dcbuffer.h" +#include "wx/sizer.h" +#include "wx/image.h" +#include "wx/settings.h" +#include "wx/menu.h" + +#include "wx/aui/auibar.h" +#include "wx/aui/framemanager.h" + +#ifdef __WXMAC__ +#include "wx/mac/carbon/private.h" +#endif + +#include "wx/arrimpl.cpp" +WX_DEFINE_OBJARRAY(wxAuiToolBarItemArray) + + +DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG) + + +IMPLEMENT_CLASS(wxAuiToolBar, wxControl) +IMPLEMENT_DYNAMIC_CLASS(wxAuiToolBarEvent, wxEvent) + + +// missing wxITEM_* items +enum +{ + wxITEM_CONTROL = wxITEM_MAX, + wxITEM_LABEL, + wxITEM_SPACER +}; + +const int BUTTON_DROPDOWN_WIDTH = 10; + + +wxBitmap wxAuiBitmapFromBits(const unsigned char bits[], int w, int h, + const wxColour& color); + +double wxAuiBlendColour(double fg, double bg, double alpha); +wxColor wxAuiStepColour(const wxColor& c, int percent); + +static wxBitmap MakeDisabledBitmap(wxBitmap& bmp) +{ + wxImage image = bmp.ConvertToImage(); + + int mr, mg, mb; + mr = image.GetMaskRed(); + mg = image.GetMaskGreen(); + mb = image.GetMaskBlue(); + + unsigned char* data = image.GetData(); + int width = image.GetWidth(); + int height = image.GetHeight(); + bool has_mask = image.HasMask(); + + for (int y = height-1; y >= 0; --y) + { + for (int x = width-1; x >= 0; --x) + { + data = image.GetData() + (y*(width*3))+(x*3); + unsigned char* r = data; + unsigned char* g = data+1; + unsigned char* b = data+2; + + if (has_mask && *r == mr && *g == mg && *b == mb) + continue; + + *r = (unsigned char)wxAuiBlendColour((double)*r, 255.0, 0.4); + *g = (unsigned char)wxAuiBlendColour((double)*g, 255.0, 0.4); + *b = (unsigned char)wxAuiBlendColour((double)*b, 255.0, 0.4); + } + } + + return wxBitmap(image); +} + +static wxColor GetBaseColor() +{ + +#ifdef __WXMAC__ + wxBrush toolbarbrush; + toolbarbrush.MacSetTheme( kThemeBrushToolbarBackground ); + wxColor base_color = toolbarbrush.GetColour(); +#else + wxColor base_color = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE); +#endif + + // the base_colour is too pale to use as our base colour, + // so darken it a bit -- + if ((255-base_color.Red()) + + (255-base_color.Green()) + + (255-base_color.Blue()) < 60) + { + base_color = wxAuiStepColour(base_color, 92); + } + + return base_color; +} + + + +class ToolbarCommandCapture : public wxEvtHandler +{ +public: + + ToolbarCommandCapture() { m_last_id = 0; } + int GetCommandId() const { return m_last_id; } + + bool ProcessEvent(wxEvent& evt) + { + if (evt.GetEventType() == wxEVT_COMMAND_MENU_SELECTED) + { + m_last_id = evt.GetId(); + return true; + } + + if (GetNextHandler()) + return GetNextHandler()->ProcessEvent(evt); + + return false; + } + +private: + int m_last_id; +}; + + + +const wxColour DISABLED_TEXT_COLOR = wxColour(wxAuiBlendColour(0,255,0.4), + wxAuiBlendColour(0,255,0.4), + wxAuiBlendColour(0,255,0.4)); + + +wxAuiDefaultToolBarArt::wxAuiDefaultToolBarArt() +{ + m_base_colour = GetBaseColor(); + + m_flags = 0; + m_text_orientation = wxAUI_TBTOOL_TEXT_BOTTOM; + m_highlight_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT); + + m_separator_size = 7; + m_gripper_size = 7; + m_overflow_size = 16; + + wxColor darker1_colour = wxAuiStepColour(m_base_colour, 85); + wxColor darker2_colour = wxAuiStepColour(m_base_colour, 75); + wxColor darker3_colour = wxAuiStepColour(m_base_colour, 60); + wxColor darker4_colour = wxAuiStepColour(m_base_colour, 50); + wxColor darker5_colour = wxAuiStepColour(m_base_colour, 40); + + m_gripper_pen1 = wxPen(darker5_colour); + m_gripper_pen2 = wxPen(darker3_colour); + m_gripper_pen3 = *wxWHITE_PEN; + + static unsigned char button_dropdown_bits[] = { 0xe0, 0xf1, 0xfb }; + static unsigned char overflow_bits[] = { 0x80, 0xff, 0x80, 0xc1, 0xe3, 0xf7 }; + + m_button_dropdown_bmp = wxAuiBitmapFromBits(button_dropdown_bits, 5, 3, + *wxBLACK); + m_disabled_button_dropdown_bmp = wxAuiBitmapFromBits( + button_dropdown_bits, 5, 3, + wxColor(128,128,128)); + m_overflow_bmp = wxAuiBitmapFromBits(overflow_bits, 7, 6, *wxBLACK); + m_disabled_overflow_bmp = wxAuiBitmapFromBits(overflow_bits, 7, 6, wxColor(128,128,128)); + + m_font = *wxNORMAL_FONT; +} + +wxAuiDefaultToolBarArt::~wxAuiDefaultToolBarArt() +{ + m_font = *wxNORMAL_FONT; +} + + +wxAuiToolBarArt* wxAuiDefaultToolBarArt::Clone() +{ + return static_cast(new wxAuiDefaultToolBarArt); +} + +void wxAuiDefaultToolBarArt::SetFlags(unsigned int flags) +{ + m_flags = flags; +} + +void wxAuiDefaultToolBarArt::SetFont(const wxFont& font) +{ + m_font = font; +} + +void wxAuiDefaultToolBarArt::SetTextOrientation(int orientation) +{ + m_text_orientation = orientation; +} + +void wxAuiDefaultToolBarArt::DrawBackground( + wxDC& dc, + wxWindow* WXUNUSED(wnd), + const wxRect& _rect) +{ + wxRect rect = _rect; + rect.height++; + wxColour start_colour = wxAuiStepColour(m_base_colour, 150); + wxColour end_colour = wxAuiStepColour(m_base_colour, 90); + dc.GradientFillLinear(rect, start_colour, end_colour, wxSOUTH); +} + +void wxAuiDefaultToolBarArt::DrawLabel( + wxDC& dc, + wxWindow* WXUNUSED(wnd), + const wxAuiToolBarItem& item, + const wxRect& rect) +{ + dc.SetFont(m_font); + dc.SetTextForeground(*wxBLACK); + + // we only care about the text height here since the text + // will get cropped based on the width of the item + int text_width = 0, text_height = 0; + dc.GetTextExtent(wxT("ABCDHgj"), &text_width, &text_height); + + // set the clipping region + wxRect clip_rect = rect; + clip_rect.width -= 1; + dc.SetClippingRegion(clip_rect); + + int text_x, text_y; + text_x = rect.x + 1; + text_y = rect.y + (rect.height-text_height)/2; + dc.DrawText(item.label, text_x, text_y); + dc.DestroyClippingRegion(); +} + + +void wxAuiDefaultToolBarArt::DrawButton( + wxDC& dc, + wxWindow* WXUNUSED(wnd), + const wxAuiToolBarItem& item, + const wxRect& rect) +{ + int text_width = 0, text_height = 0; + + if (m_flags & wxAUI_TB_TEXT) + { + dc.SetFont(m_font); + + int tx, ty; + + dc.GetTextExtent(wxT("ABCDHgj"), &tx, &text_height); + text_width = 0; + dc.GetTextExtent(item.label, &text_width, &ty); + } + + int bmp_x = 0, bmp_y = 0; + int text_x = 0, text_y = 0; + + if (m_text_orientation == wxAUI_TBTOOL_TEXT_BOTTOM) + { + bmp_x = rect.x + + (rect.width/2) - + (item.bitmap.GetWidth()/2); + + bmp_y = rect.y + + ((rect.height-text_height)/2) - + (item.bitmap.GetHeight()/2); + + text_x = rect.x + (rect.width/2) - (text_width/2) + 1; + text_y = rect.y + rect.height - text_height - 1; + } + else if (m_text_orientation == wxAUI_TBTOOL_TEXT_RIGHT) + { + bmp_x = rect.x + 3; + + bmp_y = rect.y + + (rect.height/2) - + (item.bitmap.GetHeight()/2); + + text_x = bmp_x + 3 + item.bitmap.GetWidth(); + text_y = rect.y + + (rect.height/2) - + (text_height/2); + } + + + if (!(item.state & wxAUI_BUTTON_STATE_DISABLED)) + { + if (item.state & wxAUI_BUTTON_STATE_PRESSED) + { + dc.SetPen(wxPen(m_highlight_colour)); + dc.SetBrush(wxBrush(wxAuiStepColour(m_highlight_colour, 150))); + dc.DrawRectangle(rect); + } + else if ((item.state & wxAUI_BUTTON_STATE_HOVER) || item.sticky == true) + { + dc.SetPen(wxPen(m_highlight_colour)); + dc.SetBrush(wxBrush(wxAuiStepColour(m_highlight_colour, 170))); + + // draw an even lighter background for checked item hovers (since + // the hover background is the same color as the check background) + if (item.state & wxAUI_BUTTON_STATE_CHECKED) + dc.SetBrush(wxBrush(wxAuiStepColour(m_highlight_colour, 180))); + + dc.DrawRectangle(rect); + } + else if (item.state & wxAUI_BUTTON_STATE_CHECKED) + { + // it's important to put this code in an else statment after the + // hover, otherwise hovers won't draw properly for checked items + dc.SetPen(wxPen(m_highlight_colour)); + dc.SetBrush(wxBrush(wxAuiStepColour(m_highlight_colour, 170))); + dc.DrawRectangle(rect); + } + } + + wxBitmap bmp; + if (item.state & wxAUI_BUTTON_STATE_DISABLED) + bmp = item.disabled_bitmap; + else + bmp = item.bitmap; + + if (!bmp.IsOk()) + return; + + dc.DrawBitmap(bmp, bmp_x, bmp_y, true); + + // set the item's text color based on if it is disabled + dc.SetTextForeground(*wxBLACK); + if (item.state & wxAUI_BUTTON_STATE_DISABLED) + dc.SetTextForeground(DISABLED_TEXT_COLOR); + + if ((m_flags & wxAUI_TB_TEXT) && item.label.Length() > 0) + { + dc.DrawText(item.label, text_x, text_y); + } +} + + +void wxAuiDefaultToolBarArt::DrawDropDownButton( + wxDC& dc, + wxWindow* WXUNUSED(wnd), + const wxAuiToolBarItem& item, + const wxRect& rect) +{ + int text_width = 0, text_height = 0, text_x = 0, text_y = 0; + int bmp_x = 0, bmp_y = 0, dropbmp_x = 0, dropbmp_y = 0; + + wxRect button_rect = wxRect(rect.x, + rect.y, + rect.width-BUTTON_DROPDOWN_WIDTH, + rect.height); + wxRect dropdown_rect = 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, &text_height); + text_width = 0; + } + + dc.GetTextExtent(item.label, &text_width, &ty); + } + + + + dropbmp_x = dropdown_rect.x + + (dropdown_rect.width/2) - + (m_button_dropdown_bmp.GetWidth()/2); + dropbmp_y = dropdown_rect.y + + (dropdown_rect.height/2) - + (m_button_dropdown_bmp.GetHeight()/2); + + + if (m_text_orientation == wxAUI_TBTOOL_TEXT_BOTTOM) + { + bmp_x = button_rect.x + + (button_rect.width/2) - + (item.bitmap.GetWidth()/2); + bmp_y = button_rect.y + + ((button_rect.height-text_height)/2) - + (item.bitmap.GetHeight()/2); + + text_x = rect.x + (rect.width/2) - (text_width/2) + 1; + text_y = rect.y + rect.height - text_height - 1; + } + else if (m_text_orientation == wxAUI_TBTOOL_TEXT_RIGHT) + { + bmp_x = rect.x + 3; + + bmp_y = rect.y + + (rect.height/2) - + (item.bitmap.GetHeight()/2); + + text_x = bmp_x + 3 + item.bitmap.GetWidth(); + text_y = rect.y + + (rect.height/2) - + (text_height/2); + } + + + if (item.state & wxAUI_BUTTON_STATE_PRESSED) + { + dc.SetPen(wxPen(m_highlight_colour)); + dc.SetBrush(wxBrush(wxAuiStepColour(m_highlight_colour, 140))); + dc.DrawRectangle(button_rect); + dc.DrawRectangle(dropdown_rect); + } + else if (item.state & wxAUI_BUTTON_STATE_HOVER || + item.sticky == true) + { + dc.SetPen(wxPen(m_highlight_colour)); + dc.SetBrush(wxBrush(wxAuiStepColour(m_highlight_colour, 170))); + dc.DrawRectangle(button_rect); + dc.DrawRectangle(dropdown_rect); + } + + wxBitmap bmp; + wxBitmap dropbmp; + if (item.state & wxAUI_BUTTON_STATE_DISABLED) + { + bmp = item.disabled_bitmap; + dropbmp = m_disabled_button_dropdown_bmp; + } + else + { + bmp = item.bitmap; + dropbmp = m_button_dropdown_bmp; + } + + if (!bmp.IsOk()) + return; + + dc.DrawBitmap(bmp, bmp_x, bmp_y, true); + dc.DrawBitmap(dropbmp, dropbmp_x, dropbmp_y, true); + + // set the item's text color based on if it is disabled + dc.SetTextForeground(*wxBLACK); + if (item.state & wxAUI_BUTTON_STATE_DISABLED) + dc.SetTextForeground(DISABLED_TEXT_COLOR); + + if ((m_flags & wxAUI_TB_TEXT) && item.label.Length() > 0) + { + dc.DrawText(item.label, text_x, text_y); + } +} + +void wxAuiDefaultToolBarArt::DrawControlLabel( + wxDC& dc, + wxWindow* WXUNUSED(wnd), + const wxAuiToolBarItem& item, + const wxRect& rect) +{ + if (!(m_flags & wxAUI_TB_TEXT)) + return; + + if (m_text_orientation != wxAUI_TBTOOL_TEXT_BOTTOM) + return; + + int text_x = 0, text_y = 0; + int text_width = 0, text_height = 0; + + dc.SetFont(m_font); + + int tx, ty; + if (m_flags & wxAUI_TB_TEXT) + { + dc.GetTextExtent(wxT("ABCDHgj"), &tx, &text_height); + text_width = 0; + } + + dc.GetTextExtent(item.label, &text_width, &ty); + + // don't draw the label if it is wider than the item width + if (text_width > rect.width) + return; + + // set the label's text color + dc.SetTextForeground(*wxBLACK); + + text_x = rect.x + (rect.width/2) - (text_width/2) + 1; + text_y = rect.y + rect.height - text_height - 1; + + if ((m_flags & wxAUI_TB_TEXT) && item.label.Length() > 0) + { + dc.DrawText(item.label, text_x, text_y); + } +} + +wxSize wxAuiDefaultToolBarArt::GetLabelSize( + wxDC& dc, + wxWindow* WXUNUSED(wnd), + const wxAuiToolBarItem& item) +{ + dc.SetFont(m_font); + + // get label's height + int width = 0, height = 0; + dc.GetTextExtent(wxT("ABCDHgj"), &width, &height); + + // get item's width + width = item.min_size.GetWidth(); + + return wxSize(width, height); +} + +wxSize wxAuiDefaultToolBarArt::GetToolSize( + wxDC& dc, + wxWindow* WXUNUSED(wnd), + const wxAuiToolBarItem& item) +{ + if (!item.bitmap.IsOk() && !(m_flags & wxAUI_TB_TEXT)) + return wxSize(16,16); + + int width = item.bitmap.GetWidth(); + int height = item.bitmap.GetHeight(); + + if (m_flags & wxAUI_TB_TEXT) + { + dc.SetFont(m_font); + int tx, ty; + + if (m_text_orientation == wxAUI_TBTOOL_TEXT_BOTTOM) + { + dc.GetTextExtent(wxT("ABCDHgj"), &tx, &ty); + height += ty; + + if (item.label.Length() > 0) + { + dc.GetTextExtent(item.label, &tx, &ty); + width = wxMax(width, tx+6); + } + } + else if (m_text_orientation == wxAUI_TBTOOL_TEXT_RIGHT && item.label.Length() > 0) + { + width += 3; // space between left border and bitmap + width += 3; // space between bitmap and text + + if (item.label.Length() > 0) + { + dc.GetTextExtent(item.label, &tx, &ty); + width += tx; + height = wxMax(height, ty); + } + } + } + + // if the tool has a dropdown button, add it to the width + if (item.dropdown == true) + width += (BUTTON_DROPDOWN_WIDTH+4); + + return wxSize(width, height); +} + +void wxAuiDefaultToolBarArt::DrawSeparator( + wxDC& dc, + wxWindow* WXUNUSED(wnd), + const wxRect& _rect) +{ + bool horizontal = true; + if (m_flags & wxAUI_TB_VERTICAL) + horizontal = false; + + wxRect rect = _rect; + + if (horizontal) + { + rect.x += (rect.width/2); + rect.width = 1; + int new_height = (rect.height*3)/4; + rect.y += (rect.height/2) - (new_height/2); + rect.height = new_height; + } + else + { + rect.y += (rect.height/2); + rect.height = 1; + int new_width = (rect.width*3)/4; + rect.x += (rect.width/2) - (new_width/2); + rect.width = new_width; + } + + wxColour start_colour = wxAuiStepColour(m_base_colour, 80); + wxColour end_colour = wxAuiStepColour(m_base_colour, 80); + dc.GradientFillLinear(rect, start_colour, end_colour, horizontal ? wxSOUTH : wxEAST); +} + +void wxAuiDefaultToolBarArt::DrawGripper(wxDC& dc, + wxWindow* WXUNUSED(wnd), + const wxRect& rect) +{ + int i = 0; + while (1) + { + int x, y; + + if (m_flags & wxAUI_TB_VERTICAL) + { + x = rect.x + (i*4) + 5; + y = rect.y + 3; + if (x > rect.GetWidth()-5) + break; + } + else + { + x = rect.x + 3; + y = rect.y + (i*4) + 5; + if (y > rect.GetHeight()-5) + break; + } + + dc.SetPen(m_gripper_pen1); + dc.DrawPoint(x, y); + dc.SetPen(m_gripper_pen2); + dc.DrawPoint(x, y+1); + dc.DrawPoint(x+1, y); + dc.SetPen(m_gripper_pen3); + dc.DrawPoint(x+2, y+1); + dc.DrawPoint(x+2, y+2); + dc.DrawPoint(x+1, y+2); + + i++; + } + +} + +void wxAuiDefaultToolBarArt::DrawOverflowButton(wxDC& dc, + wxWindow* wnd, + const wxRect& rect, + int state) +{ + if (state & wxAUI_BUTTON_STATE_HOVER || + state & wxAUI_BUTTON_STATE_PRESSED) + { + wxRect cli_rect = wnd->GetClientRect(); + wxColor light_gray_bg = wxAuiStepColour(m_highlight_colour, 170); + + if (m_flags & wxAUI_TB_VERTICAL) + { + dc.SetPen(wxPen(m_highlight_colour)); + dc.DrawLine(rect.x, rect.y, rect.x+rect.width, rect.y); + dc.SetPen(wxPen(light_gray_bg)); + dc.SetBrush(wxBrush(light_gray_bg)); + dc.DrawRectangle(rect.x, rect.y+1, rect.width, rect.height); + } + else + { + dc.SetPen(wxPen(m_highlight_colour)); + dc.DrawLine(rect.x, rect.y, rect.x, rect.y+rect.height); + dc.SetPen(wxPen(light_gray_bg)); + dc.SetBrush(wxBrush(light_gray_bg)); + dc.DrawRectangle(rect.x+1, rect.y, rect.width, rect.height); + } + } + + int x = rect.x+1+(rect.width-m_overflow_bmp.GetWidth())/2; + int y = rect.y+1+(rect.height-m_overflow_bmp.GetHeight())/2; + dc.DrawBitmap(m_overflow_bmp, x, y, true); +} + +int wxAuiDefaultToolBarArt::GetElementSize(int element_id) +{ + switch (element_id) + { + case wxAUI_TBART_SEPARATOR_SIZE: return m_separator_size; + case wxAUI_TBART_GRIPPER_SIZE: return m_gripper_size; + case wxAUI_TBART_OVERFLOW_SIZE: return m_overflow_size; + default: return 0; + } +} + +void wxAuiDefaultToolBarArt::SetElementSize(int element_id, int size) +{ + switch (element_id) + { + case wxAUI_TBART_SEPARATOR_SIZE: m_separator_size = size; + case wxAUI_TBART_GRIPPER_SIZE: m_gripper_size = size; + case wxAUI_TBART_OVERFLOW_SIZE: m_overflow_size = size; + } +} + +int wxAuiDefaultToolBarArt::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.kind == wxITEM_NORMAL) + { + wxString text = item.short_help; + if (text.empty()) + text = item.label; + + if (text.empty()) + text = wxT(" "); + + #ifdef __WXMAC__ + wxMenuItem* m = new wxMenuItem(&menuPopup, item.id, text, item.short_help); + #else + wxMenuItem* m = new wxMenuItem(&menuPopup, item.id, text, item.short_help, false); + #endif + + m->SetBitmap(item.bitmap); + menuPopup.Append(m); + items_added++; + } + else if (item.kind == 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; +} + + + + +BEGIN_EVENT_TABLE(wxAuiToolBar, wxControl) + EVT_SIZE(wxAuiToolBar::OnSize) + EVT_IDLE(wxAuiToolBar::OnIdle) + EVT_ERASE_BACKGROUND(wxAuiToolBar::OnEraseBackground) + EVT_PAINT(wxAuiToolBar::OnPaint) + EVT_LEFT_DOWN(wxAuiToolBar::OnLeftDown) + EVT_LEFT_DCLICK(wxAuiToolBar::OnLeftDown) + EVT_LEFT_UP(wxAuiToolBar::OnLeftUp) + EVT_RIGHT_DOWN(wxAuiToolBar::OnRightDown) + EVT_RIGHT_DCLICK(wxAuiToolBar::OnRightDown) + EVT_RIGHT_UP(wxAuiToolBar::OnRightUp) + EVT_MIDDLE_DOWN(wxAuiToolBar::OnMiddleDown) + EVT_MIDDLE_DCLICK(wxAuiToolBar::OnMiddleDown) + EVT_MIDDLE_UP(wxAuiToolBar::OnMiddleUp) + EVT_MOTION(wxAuiToolBar::OnMotion) + EVT_LEAVE_WINDOW(wxAuiToolBar::OnLeaveWindow) + EVT_SET_CURSOR(wxAuiToolBar::OnSetCursor) +END_EVENT_TABLE() + + +wxAuiToolBar::wxAuiToolBar(wxWindow* parent, + wxWindowID id, + const wxPoint& position, + const wxSize& size, + long style) + : wxControl(parent, + id, + position, + size, + style | wxBORDER_NONE) +{ + m_sizer = new wxBoxSizer(wxHORIZONTAL); + m_button_width = -1; + m_button_height = -1; + m_sizer_element_count = 0; + m_action_pos = wxPoint(-1,-1); + m_action_item = NULL; + m_tip_item = NULL; + m_art = new wxAuiDefaultToolBarArt; + m_tool_packing = 2; + m_tool_border_padding = 3; + m_tool_text_orientation = wxAUI_TBTOOL_TEXT_BOTTOM; + m_gripper_sizer_item = NULL; + m_overflow_sizer_item = NULL; + m_dragging = false; + m_style = style; + m_gripper_visible = (m_style & wxAUI_TB_GRIPPER) ? true : false; + m_overflow_visible = (m_style & wxAUI_TB_OVERFLOW) ? true : false; + m_overflow_state = 0; + SetMargins(5, 5, 2, 2); + SetFont(*wxNORMAL_FONT); + m_art->SetFlags((unsigned int)m_style); + SetExtraStyle(wxWS_EX_PROCESS_IDLE); + if (style & wxAUI_TB_HORZ_TEXT) + SetToolTextOrientation(wxAUI_TBTOOL_TEXT_RIGHT); +} + + +wxAuiToolBar::~wxAuiToolBar() +{ + delete m_art; + delete m_sizer; +} + +void wxAuiToolBar::SetWindowStyleFlag(long style) +{ + wxControl::SetWindowStyleFlag(style); + + m_style = style; + + if (m_art) + { + m_art->SetFlags((unsigned int)m_style); + } + + if (m_style & wxAUI_TB_GRIPPER) + m_gripper_visible = true; + else + m_gripper_visible = false; + + + if (m_style & wxAUI_TB_OVERFLOW) + m_overflow_visible = true; + else + m_overflow_visible = false; + + if (style & wxAUI_TB_HORZ_TEXT) + SetToolTextOrientation(wxAUI_TBTOOL_TEXT_RIGHT); + else + SetToolTextOrientation(wxAUI_TBTOOL_TEXT_BOTTOM); +} + + +void wxAuiToolBar::SetArtProvider(wxAuiToolBarArt* art) +{ + delete m_art; + + m_art = art; + + if (m_art) + { + m_art->SetFlags((unsigned int)m_style); + m_art->SetTextOrientation(m_tool_text_orientation); + } +} + +wxAuiToolBarArt* wxAuiToolBar::GetArtProvider() const +{ + return m_art; +} + + + + +void wxAuiToolBar::AddTool(int tool_id, + const wxString& label, + const wxBitmap& bitmap, + const wxString& short_help_string, + wxItemKind kind) +{ + AddTool(tool_id, + label, + bitmap, + wxNullBitmap, + kind, + short_help_string, + wxEmptyString, + NULL); +} + + +void wxAuiToolBar::AddTool(int tool_id, + const wxString& label, + const wxBitmap& bitmap, + const wxBitmap& disabled_bitmap, + wxItemKind kind, + const wxString& WXUNUSED(short_help_string), + const wxString& WXUNUSED(long_help_string), + wxObject* WXUNUSED(client_data)) +{ + wxAuiToolBarItem item; + item.window = NULL; + item.label = label; + item.bitmap = bitmap; + item.disabled_bitmap = disabled_bitmap; + item.active = true; + item.dropdown = false; + item.space_pixels = 0; + item.id = tool_id; + item.state = 0; + item.proportion = 0; + item.kind = kind; + item.sizer_item = NULL; + item.min_size = wxDefaultSize; + item.user_data = 0; + item.sticky = false; + + if (!item.disabled_bitmap.IsOk()) + { + // no disabled bitmap specified, we need to make one + if (item.bitmap.IsOk()) + { + //wxImage img = item.bitmap.ConvertToImage(); + //wxImage grey_version = img.ConvertToGreyscale(); + //item.disabled_bitmap = wxBitmap(grey_version); + item.disabled_bitmap = MakeDisabledBitmap(item.bitmap); + } + } + + m_items.Add(item); +} + +void wxAuiToolBar::AddControl(wxControl* control, + const wxString& label) +{ + wxAuiToolBarItem item; + item.window = (wxWindow*)control; + item.label = label; + item.bitmap = wxNullBitmap; + item.disabled_bitmap = wxNullBitmap; + item.active = true; + item.dropdown = false; + item.space_pixels = 0; + item.id = control->GetId(); + item.state = 0; + item.proportion = 0; + item.kind = wxITEM_CONTROL; + item.sizer_item = NULL; + item.min_size = control->GetEffectiveMinSize(); + item.user_data = 0; + item.sticky = false; + + m_items.Add(item); +} + +void wxAuiToolBar::AddLabel(int tool_id, + const wxString& label, + const int width) +{ + wxSize min_size = wxDefaultSize; + if (width != -1) + min_size.x = width; + + wxAuiToolBarItem item; + item.window = NULL; + item.label = label; + item.bitmap = wxNullBitmap; + item.disabled_bitmap = wxNullBitmap; + item.active = true; + item.dropdown = false; + item.space_pixels = 0; + item.id = tool_id; + item.state = 0; + item.proportion = 0; + item.kind = wxITEM_LABEL; + item.sizer_item = NULL; + item.min_size = min_size; + item.user_data = 0; + item.sticky = false; + + m_items.Add(item); +} + +void wxAuiToolBar::AddSeparator() +{ + wxAuiToolBarItem item; + item.window = NULL; + item.label = wxEmptyString; + item.bitmap = wxNullBitmap; + item.disabled_bitmap = wxNullBitmap; + item.active = true; + item.dropdown = false; + item.id = -1; + item.state = 0; + item.proportion = 0; + item.kind = wxITEM_SEPARATOR; + item.sizer_item = NULL; + item.min_size = wxDefaultSize; + item.user_data = 0; + item.sticky = false; + + m_items.Add(item); +} + +void wxAuiToolBar::AddSpacer(int pixels) +{ + wxAuiToolBarItem item; + item.window = NULL; + item.label = wxEmptyString; + item.bitmap = wxNullBitmap; + item.disabled_bitmap = wxNullBitmap; + item.active = true; + item.dropdown = false; + item.space_pixels = pixels; + item.id = -1; + item.state = 0; + item.proportion = 0; + item.kind = wxITEM_SPACER; + item.sizer_item = NULL; + item.min_size = wxDefaultSize; + item.user_data = 0; + item.sticky = false; + + m_items.Add(item); +} + +void wxAuiToolBar::AddStretchSpacer(int proportion) +{ + wxAuiToolBarItem item; + item.window = NULL; + item.label = wxEmptyString; + item.bitmap = wxNullBitmap; + item.disabled_bitmap = wxNullBitmap; + item.active = true; + item.dropdown = false; + item.space_pixels = 0; + item.id = -1; + item.state = 0; + item.proportion = proportion; + item.kind = wxITEM_SPACER; + item.sizer_item = NULL; + item.min_size = wxDefaultSize; + item.user_data = 0; + item.sticky = false; + + m_items.Add(item); +} + +void wxAuiToolBar::Clear() +{ + m_items.Clear(); + m_sizer_element_count = 0; +} + +bool wxAuiToolBar::DeleteTool(int tool_id) +{ + int idx = GetToolIndex(tool_id); + if (idx >= 0 && idx < (int)m_items.GetCount()) + { + m_items.RemoveAt(idx); + Realize(); + return true; + } + + return false; +} + +bool wxAuiToolBar::DeleteByIndex(int idx) +{ + if (idx >= 0 && idx < (int)m_items.GetCount()) + { + m_items.RemoveAt(idx); + Realize(); + return true; + } + + return false; +} + + +wxControl* wxAuiToolBar::FindControl(int id) +{ + wxWindow* wnd = FindWindow(id); + return (wxControl*)wnd; +} + +wxAuiToolBarItem* wxAuiToolBar::FindTool(int tool_id) const +{ + size_t i, count; + for (i = 0, count = m_items.GetCount(); i < count; ++i) + { + wxAuiToolBarItem& item = m_items.Item(i); + if (item.id == tool_id) + return &item; + } + + return NULL; +} + +wxAuiToolBarItem* wxAuiToolBar::FindToolByPosition(wxCoord x, wxCoord y) const +{ + size_t i, count; + for (i = 0, count = m_items.GetCount(); i < count; ++i) + { + wxAuiToolBarItem& item = m_items.Item(i); + + if (!item.sizer_item) + continue; + + wxRect rect = item.sizer_item->GetRect(); + if (rect.Contains(x,y)) + { + // if the item doesn't fit on the toolbar, return NULL + if (!GetToolFitsByIndex(i)) + return NULL; + + return &item; + } + } + + return NULL; +} + +wxAuiToolBarItem* wxAuiToolBar::FindToolByPositionWithPacking(wxCoord x, wxCoord y) const +{ + size_t i, count; + for (i = 0, count = m_items.GetCount(); i < count; ++i) + { + wxAuiToolBarItem& item = m_items.Item(i); + + if (!item.sizer_item) + continue; + + wxRect rect = item.sizer_item->GetRect(); + + // apply tool packing + if (i+1 < count) + rect.width += m_tool_packing; + + if (rect.Contains(x,y)) + { + // if the item doesn't fit on the toolbar, return NULL + if (!GetToolFitsByIndex(i)) + return NULL; + + return &item; + } + } + + return NULL; +} + +wxAuiToolBarItem* wxAuiToolBar::FindToolByIndex(int idx) const +{ + if (idx < 0) + return NULL; + + if (idx >= (int)m_items.size()) + return NULL; + + return &(m_items[idx]); +} + +void wxAuiToolBar::SetToolBitmapSize(const wxSize& WXUNUSED(size)) +{ + // TODO: wxToolBar compatibility +} + +wxSize wxAuiToolBar::GetToolBitmapSize() const +{ + // TODO: wxToolBar compatibility + return wxSize(16,15); +} + +void wxAuiToolBar::SetToolProportion(int tool_id, int proportion) +{ + wxAuiToolBarItem* item = FindTool(tool_id); + if (!item) + return; + + item->proportion = proportion; +} + +int wxAuiToolBar::GetToolProportion(int tool_id) const +{ + wxAuiToolBarItem* item = FindTool(tool_id); + if (!item) + return 0; + + return item->proportion; +} + +void wxAuiToolBar::SetToolSeparation(int separation) +{ + if (m_art) + m_art->SetElementSize(wxAUI_TBART_SEPARATOR_SIZE, separation); +} + +int wxAuiToolBar::GetToolSeparation() const +{ + if (m_art) + return m_art->GetElementSize(wxAUI_TBART_SEPARATOR_SIZE); + else + return 5; +} + + +void wxAuiToolBar::SetToolDropDown(int tool_id, bool dropdown) +{ + wxAuiToolBarItem* item = FindTool(tool_id); + if (!item) + return; + + item->dropdown = dropdown; +} + +bool wxAuiToolBar::GetToolDropDown(int tool_id) const +{ + wxAuiToolBarItem* item = FindTool(tool_id); + if (!item) + return 0; + + return item->dropdown; +} + +void wxAuiToolBar::SetToolSticky(int tool_id, bool sticky) +{ + // ignore separators + if (tool_id == -1) + return; + + wxAuiToolBarItem* item = FindTool(tool_id); + if (!item) + return; + + if (item->sticky == sticky) + return; + + item->sticky = sticky; + + Refresh(false); + Update(); +} + +bool wxAuiToolBar::GetToolSticky(int tool_id) const +{ + wxAuiToolBarItem* item = FindTool(tool_id); + if (!item) + return 0; + + return item->sticky; +} + + + + +void wxAuiToolBar::SetToolBorderPadding(int padding) +{ + m_tool_border_padding = padding; +} + +int wxAuiToolBar::GetToolBorderPadding() const +{ + return m_tool_border_padding; +} + +void wxAuiToolBar::SetToolTextOrientation(int orientation) +{ + m_tool_text_orientation = orientation; + + if (m_art) + { + m_art->SetTextOrientation(orientation); + } +} + +int wxAuiToolBar::GetToolTextOrientation() const +{ + return m_tool_text_orientation; +} + +void wxAuiToolBar::SetToolPacking(int packing) +{ + m_tool_packing = packing; +} + +int wxAuiToolBar::GetToolPacking() const +{ + return m_tool_packing; +} + + +void wxAuiToolBar::SetOrientation(int WXUNUSED(orientation)) +{ +} + +void wxAuiToolBar::SetMargins(int left, int right, int top, int bottom) +{ + if (left != -1) + m_left_padding = left; + if (right != -1) + m_right_padding = right; + if (top != -1) + m_top_padding = top; + if (bottom != -1) + m_bottom_padding = bottom; +} + +bool wxAuiToolBar::GetGripperVisible() const +{ + return m_gripper_visible; +} + +void wxAuiToolBar::SetGripperVisible(bool visible) +{ + m_gripper_visible = visible; + if (visible) + m_style |= wxAUI_TB_GRIPPER; + Realize(); + Refresh(false); +} + + +bool wxAuiToolBar::GetOverflowVisible() const +{ + return m_overflow_visible; +} + +void wxAuiToolBar::SetOverflowVisible(bool visible) +{ + m_overflow_visible = visible; + if (visible) + m_style |= wxAUI_TB_OVERFLOW; + Refresh(false); +} + +bool wxAuiToolBar::SetFont(const wxFont& font) +{ + bool res = wxWindow::SetFont(font); + + if (m_art) + { + m_art->SetFont(font); + } + + return res; +} + + +void wxAuiToolBar::SetHoverItem(wxAuiToolBarItem* pitem) +{ + wxAuiToolBarItem* former_hover = NULL; + + size_t i, count; + for (i = 0, count = m_items.GetCount(); i < count; ++i) + { + wxAuiToolBarItem& item = m_items.Item(i); + if (item.state & wxAUI_BUTTON_STATE_HOVER) + former_hover = &item; + item.state &= ~wxAUI_BUTTON_STATE_HOVER; + } + + if (pitem) + { + pitem->state |= wxAUI_BUTTON_STATE_HOVER; + } + + if (former_hover != pitem) + { + Refresh(false); + Update(); + } +} + +void wxAuiToolBar::SetPressedItem(wxAuiToolBarItem* pitem) +{ + wxAuiToolBarItem* former_item = NULL; + + size_t i, count; + for (i = 0, count = m_items.GetCount(); i < count; ++i) + { + wxAuiToolBarItem& item = m_items.Item(i); + if (item.state & wxAUI_BUTTON_STATE_PRESSED) + former_item = &item; + item.state &= ~wxAUI_BUTTON_STATE_PRESSED; + } + + if (pitem) + { + pitem->state &= ~wxAUI_BUTTON_STATE_HOVER; + pitem->state |= wxAUI_BUTTON_STATE_PRESSED; + } + + if (former_item != pitem) + { + Refresh(false); + Update(); + } +} + +void wxAuiToolBar::RefreshOverflowState() +{ + if (!m_overflow_sizer_item) + { + m_overflow_state = 0; + return; + } + + int overflow_state = 0; + + wxRect overflow_rect = GetOverflowRect(); + + + // find out the mouse's current position + wxPoint pt = ::wxGetMousePosition(); + pt = this->ScreenToClient(pt); + + // find out if the mouse cursor is inside the dropdown rectangle + if (overflow_rect.Contains(pt.x, pt.y)) + { + if (::wxGetMouseState().LeftDown()) + overflow_state = wxAUI_BUTTON_STATE_PRESSED; + else + overflow_state = wxAUI_BUTTON_STATE_HOVER; + } + + if (overflow_state != m_overflow_state) + { + m_overflow_state = overflow_state; + Refresh(false); + Update(); + } + + m_overflow_state = overflow_state; +} + +void wxAuiToolBar::ToggleTool(int tool_id, bool state) +{ + wxAuiToolBarItem* tool = FindTool(tool_id); + + if (tool) + { + if (tool->kind != wxITEM_CHECK) + return; + + if (state == true) + tool->state |= wxAUI_BUTTON_STATE_CHECKED; + else + tool->state &= ~wxAUI_BUTTON_STATE_CHECKED; + } +} + +bool wxAuiToolBar::GetToolToggled(int tool_id) const +{ + wxAuiToolBarItem* tool = FindTool(tool_id); + + if (tool) + { + if (tool->kind != wxITEM_CHECK) + return false; + + return (tool->state & wxAUI_BUTTON_STATE_CHECKED) ? true : false; + } + + return false; +} + +void wxAuiToolBar::EnableTool(int tool_id, bool state) +{ + wxAuiToolBarItem* tool = FindTool(tool_id); + + if (tool) + { + if (state == true) + tool->state &= ~wxAUI_BUTTON_STATE_DISABLED; + else + tool->state |= wxAUI_BUTTON_STATE_DISABLED; + } +} + +bool wxAuiToolBar::GetToolEnabled(int tool_id) const +{ + wxAuiToolBarItem* tool = FindTool(tool_id); + + if (tool) + return (tool->state & wxAUI_BUTTON_STATE_DISABLED) ? false : true; + + return false; +} + +wxString wxAuiToolBar::GetToolLabel(int tool_id) const +{ + wxAuiToolBarItem* tool = FindTool(tool_id); + wxASSERT_MSG(tool, wxT("can't find tool in toolbar item array")); + if (!tool) + return wxEmptyString; + + return tool->label; +} + +void wxAuiToolBar::SetToolLabel(int tool_id, const wxString& label) +{ + wxAuiToolBarItem* tool = FindTool(tool_id); + if (tool) + { + tool->label = label; + } +} + +wxBitmap wxAuiToolBar::GetToolBitmap(int tool_id) const +{ + wxAuiToolBarItem* tool = FindTool(tool_id); + wxASSERT_MSG(tool, wxT("can't find tool in toolbar item array")); + if (!tool) + return wxNullBitmap; + + return tool->bitmap; +} + +void wxAuiToolBar::SetToolBitmap(int tool_id, const wxBitmap& bitmap) +{ + wxAuiToolBarItem* tool = FindTool(tool_id); + if (tool) + { + tool->bitmap = bitmap; + } +} + +wxString wxAuiToolBar::GetToolShortHelp(int tool_id) const +{ + wxAuiToolBarItem* tool = FindTool(tool_id); + wxASSERT_MSG(tool, wxT("can't find tool in toolbar item array")); + if (!tool) + return wxEmptyString; + + return tool->short_help; +} + +void wxAuiToolBar::SetToolShortHelp(int tool_id, const wxString& help_string) +{ + wxAuiToolBarItem* tool = FindTool(tool_id); + if (tool) + { + tool->short_help = help_string; + } +} + +wxString wxAuiToolBar::GetToolLongHelp(int tool_id) const +{ + wxAuiToolBarItem* tool = FindTool(tool_id); + wxASSERT_MSG(tool, wxT("can't find tool in toolbar item array")); + if (!tool) + return wxEmptyString; + + return tool->long_help; +} + +void wxAuiToolBar::SetToolLongHelp(int tool_id, const wxString& help_string) +{ + wxAuiToolBarItem* tool = FindTool(tool_id); + if (tool) + { + tool->long_help = help_string; + } +} + +void wxAuiToolBar::SetCustomOverflowItems(const wxAuiToolBarItemArray& prepend, + const wxAuiToolBarItemArray& append) +{ + m_custom_overflow_prepend = prepend; + m_custom_overflow_append = append; +} + + +size_t wxAuiToolBar::GetToolCount() const +{ + return m_items.size(); +} + +int wxAuiToolBar::GetToolIndex(int tool_id) const +{ + // this will prevent us from returning the index of the + // first separator in the toolbar since its id is equal to -1 + if (tool_id == -1) + return wxNOT_FOUND; + + size_t i, count = m_items.GetCount(); + for (i = 0; i < count; ++i) + { + wxAuiToolBarItem& item = m_items.Item(i); + if (item.id == tool_id) + return i; + } + + return wxNOT_FOUND; +} + +bool wxAuiToolBar::GetToolFitsByIndex(int tool_idx) const +{ + if (tool_idx < 0 || tool_idx >= (int)m_items.GetCount()) + return false; + + if (!m_items[tool_idx].sizer_item) + return false; + + int cli_w, cli_h; + GetClientSize(&cli_w, &cli_h); + + wxRect rect = m_items[tool_idx].sizer_item->GetRect(); + + if (m_style & wxAUI_TB_VERTICAL) + { + // take the dropdown size into account + if (m_overflow_visible) + cli_h -= m_overflow_sizer_item->GetSize().y; + + if (rect.y+rect.height < cli_h) + return true; + } + else + { + // take the dropdown size into account + if (m_overflow_visible) + cli_w -= m_overflow_sizer_item->GetSize().x; + + if (rect.x+rect.width < cli_w) + return true; + } + + return false; +} + + +bool wxAuiToolBar::GetToolFits(int tool_id) const +{ + return GetToolFitsByIndex(GetToolIndex(tool_id)); +} + +wxRect wxAuiToolBar::GetToolRect(int tool_id) const +{ + wxAuiToolBarItem* tool = FindTool(tool_id); + if (tool && tool->sizer_item) + { + return tool->sizer_item->GetRect(); + } + + return wxRect(); +} + +bool wxAuiToolBar::GetToolBarFits() const +{ + if (m_items.GetCount() == 0) + { + // empty toolbar always 'fits' + return true; + } + + // entire toolbar content fits if the last tool fits + return GetToolFitsByIndex(m_items.GetCount() - 1); +} + +bool wxAuiToolBar::Realize() +{ + wxClientDC dc(this); + if (!dc.IsOk()) + return false; + + bool horizontal = true; + if (m_style & wxAUI_TB_VERTICAL) + horizontal = false; + + + // create the new sizer to add toolbar elements to + wxBoxSizer* sizer = new wxBoxSizer(horizontal ? wxHORIZONTAL : wxVERTICAL); + + // add gripper area + int separator_size = m_art->GetElementSize(wxAUI_TBART_SEPARATOR_SIZE); + int gripper_size = m_art->GetElementSize(wxAUI_TBART_GRIPPER_SIZE); + if (gripper_size > 0 && m_gripper_visible) + { + if (horizontal) + m_gripper_sizer_item = sizer->Add(gripper_size, 1, 0, wxEXPAND); + else + m_gripper_sizer_item = sizer->Add(1, gripper_size, 0, wxEXPAND); + } + else + { + m_gripper_sizer_item = NULL; + } + + // add "left" padding + if (m_left_padding > 0) + { + if (horizontal) + sizer->Add(m_left_padding, 1); + else + sizer->Add(1, m_left_padding); + } + + size_t i, count; + for (i = 0, count = m_items.GetCount(); i < count; ++i) + { + wxAuiToolBarItem& item = m_items.Item(i); + wxSizerItem* sizer_item = NULL; + + switch (item.kind) + { + case wxITEM_LABEL: + { + wxSize size = m_art->GetLabelSize(dc, this, item); + sizer_item = sizer->Add(size.x + (m_tool_border_padding*2), + size.y + (m_tool_border_padding*2), + item.proportion, + wxALIGN_CENTER); + if (i+1 < count) + { + sizer->AddSpacer(m_tool_packing); + } + + break; + } + + case wxITEM_CHECK: + case wxITEM_NORMAL: + { + wxSize size = m_art->GetToolSize(dc, this, item); + sizer_item = sizer->Add(size.x + (m_tool_border_padding*2), + size.y + (m_tool_border_padding*2), + 0, + wxALIGN_CENTER); + // add tool packing + if (i+1 < count) + { + sizer->AddSpacer(m_tool_packing); + } + + break; + } + + case wxITEM_SEPARATOR: + { + if (horizontal) + sizer_item = sizer->Add(separator_size, 1, 0, wxEXPAND); + else + sizer_item = sizer->Add(1, separator_size, 0, wxEXPAND); + + // add tool packing + if (i+1 < count) + { + sizer->AddSpacer(m_tool_packing); + } + + break; + } + + case wxITEM_SPACER: + if (item.proportion > 0) + sizer_item = sizer->AddStretchSpacer(item.proportion); + else + sizer_item = sizer->Add(item.space_pixels, 1); + break; + + case wxITEM_CONTROL: + { + //sizer_item = sizer->Add(item.window, item.proportion, wxEXPAND); + wxSizerItem* ctrl_sizer_item; + + wxBoxSizer* vert_sizer = new wxBoxSizer(wxVERTICAL); + vert_sizer->AddStretchSpacer(1); + ctrl_sizer_item = vert_sizer->Add(item.window, 0, wxEXPAND); + vert_sizer->AddStretchSpacer(1); + if ((m_style & wxAUI_TB_TEXT) && item.label.Length() > 0) + { + wxSize s = GetLabelSize(item.label); + vert_sizer->Add(1, s.y); + } + + + sizer_item = sizer->Add(vert_sizer, item.proportion, wxEXPAND); + + wxSize min_size = item.min_size; + + + // proportional items will disappear from the toolbar if + // their min width is not set to something really small + if (item.proportion != 0) + { + min_size.x = 1; + } + + if (min_size.IsFullySpecified()) + { + sizer_item->SetMinSize(min_size); + ctrl_sizer_item->SetMinSize(min_size); + } + + // add tool packing + if (i+1 < count) + { + sizer->AddSpacer(m_tool_packing); + } + } + } + + item.sizer_item = sizer_item; + } + + // add "right" padding + if (m_right_padding > 0) + { + if (horizontal) + sizer->Add(m_right_padding, 1); + else + sizer->Add(1, m_right_padding); + } + + // add drop down area + m_overflow_sizer_item = NULL; + + if (m_style & wxAUI_TB_OVERFLOW) + { + int overflow_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE); + if (overflow_size > 0 && m_overflow_visible) + { + if (horizontal) + m_overflow_sizer_item = sizer->Add(overflow_size, 1, 0, wxEXPAND); + else + m_overflow_sizer_item = sizer->Add(1, overflow_size, 0, wxEXPAND); + } + else + { + m_overflow_sizer_item = NULL; + } + } + + + // the outside sizer helps us apply the "top" and "bottom" padding + wxBoxSizer* outside_sizer = new wxBoxSizer(horizontal ? wxVERTICAL : wxHORIZONTAL); + + // add "top" padding + if (m_top_padding > 0) + { + if (horizontal) + outside_sizer->Add(1, m_top_padding); + else + outside_sizer->Add(m_top_padding, 1); + } + + // add the sizer that contains all of the toolbar elements + outside_sizer->Add(sizer, 1, wxEXPAND); + + // add "bottom" padding + if (m_bottom_padding > 0) + { + if (horizontal) + outside_sizer->Add(1, m_bottom_padding); + else + outside_sizer->Add(m_bottom_padding, 1); + } + + delete m_sizer; // remove old sizer + m_sizer = outside_sizer; + + // calculate the rock-bottom minimum size + for (i = 0, count = m_items.GetCount(); i < count; ++i) + { + wxAuiToolBarItem& item = m_items.Item(i); + if (item.sizer_item && item.proportion > 0 && item.min_size.IsFullySpecified()) + item.sizer_item->SetMinSize(0,0); + } + + m_absolute_min_size = m_sizer->GetMinSize(); + + // reset the min sizes to what they were + for (i = 0, count = m_items.GetCount(); i < count; ++i) + { + wxAuiToolBarItem& item = m_items.Item(i); + if (item.sizer_item && item.proportion > 0 && item.min_size.IsFullySpecified()) + item.sizer_item->SetMinSize(item.min_size); + } + + // set control size + wxSize size = m_sizer->GetMinSize(); + m_minWidth = size.x; + m_minHeight = size.y; + + if ((m_style & wxAUI_TB_NO_AUTORESIZE) == 0) + { + wxSize cur_size = GetClientSize(); + wxSize new_size = GetMinSize(); + if (new_size != cur_size) + { + SetClientSize(new_size); + } + else + { + m_sizer->SetDimension(0, 0, cur_size.x, cur_size.y); + } + } + else + { + wxSize cur_size = GetClientSize(); + m_sizer->SetDimension(0, 0, cur_size.x, cur_size.y); + } + + Refresh(false); + return true; +} + +int wxAuiToolBar::GetOverflowState() const +{ + return m_overflow_state; +} + +wxRect wxAuiToolBar::GetOverflowRect() const +{ + wxRect cli_rect(wxPoint(0,0), GetClientSize()); + wxRect overflow_rect = m_overflow_sizer_item->GetRect(); + int overflow_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE); + + if (m_style & wxAUI_TB_VERTICAL) + { + overflow_rect.y = cli_rect.height - overflow_size; + overflow_rect.x = 0; + overflow_rect.width = cli_rect.width; + overflow_rect.height = overflow_size; + } + else + { + overflow_rect.x = cli_rect.width - overflow_size; + overflow_rect.y = 0; + overflow_rect.width = overflow_size; + overflow_rect.height = cli_rect.height; + } + + return overflow_rect; +} + +wxSize wxAuiToolBar::GetLabelSize(const wxString& label) +{ + wxClientDC dc(this); + + int tx, ty; + int text_width = 0, text_height = 0; + + dc.SetFont(m_font); + + // get the text height + dc.GetTextExtent(wxT("ABCDHgj"), &tx, &text_height); + + // get the text width + dc.GetTextExtent(label, &text_width, &ty); + + return wxSize(text_width, text_height); +} + + +void wxAuiToolBar::DoIdleUpdate() +{ + wxEvtHandler* handler = GetEventHandler(); + + bool need_refresh = false; + + size_t i, count; + for (i = 0, count = m_items.GetCount(); i < count; ++i) + { + wxAuiToolBarItem& item = m_items.Item(i); + + if (item.id == -1) + continue; + + wxUpdateUIEvent evt(item.id); + evt.SetEventObject(this); + + if (handler->ProcessEvent(evt)) + { + if (evt.GetSetEnabled()) + { + bool is_enabled; + if (item.window) + is_enabled = item.window->IsEnabled(); + else + is_enabled = (item.state & wxAUI_BUTTON_STATE_DISABLED) ? false : true; + + bool new_enabled = evt.GetEnabled(); + if (new_enabled != is_enabled) + { + if (item.window) + { + item.window->Enable(new_enabled); + } + else + { + if (new_enabled) + item.state &= ~wxAUI_BUTTON_STATE_DISABLED; + else + item.state |= wxAUI_BUTTON_STATE_DISABLED; + } + need_refresh = true; + } + } + + if (evt.GetSetChecked()) + { + // make sure we aren't checking an item that can't be + if (item.kind != wxITEM_CHECK && item.kind != wxITEM_RADIO) + continue; + + bool is_checked = (item.state & wxAUI_BUTTON_STATE_CHECKED) ? true : false; + bool new_checked = evt.GetChecked(); + + if (new_checked != is_checked) + { + if (new_checked) + item.state |= wxAUI_BUTTON_STATE_CHECKED; + else + item.state &= ~wxAUI_BUTTON_STATE_CHECKED; + + need_refresh = true; + } + } + + } + } + + + if (need_refresh) + { + Refresh(false); + } +} + + +void wxAuiToolBar::OnSize(wxSizeEvent& WXUNUSED(evt)) +{ + int x, y; + GetClientSize(&x, &y); + + if (x > y) + SetOrientation(wxHORIZONTAL); + else + SetOrientation(wxVERTICAL); + + if (((x >= y) && m_absolute_min_size.x > x) || + ((y > x) && m_absolute_min_size.y > y)) + { + // hide all flexible items + size_t i, count; + for (i = 0, count = m_items.GetCount(); i < count; ++i) + { + wxAuiToolBarItem& item = m_items.Item(i); + if (item.sizer_item && item.proportion > 0 && item.sizer_item->IsShown()) + { + item.sizer_item->Show(false); + item.sizer_item->SetProportion(0); + } + } + } + else + { + // show all flexible items + size_t i, count; + for (i = 0, count = m_items.GetCount(); i < count; ++i) + { + wxAuiToolBarItem& item = m_items.Item(i); + if (item.sizer_item && item.proportion > 0 && !item.sizer_item->IsShown()) + { + item.sizer_item->Show(true); + item.sizer_item->SetProportion(item.proportion); + } + } + } + + m_sizer->SetDimension(0, 0, x, y); + + Refresh(false); + Update(); +} + + + +void wxAuiToolBar::DoSetSize(int x, + int y, + int width, + int height, + int sizeFlags) +{ + wxSize parent_size = GetParent()->GetClientSize(); + if (x + width > parent_size.x) + width = wxMax(0, parent_size.x - x); + if (y + height > parent_size.y) + height = wxMax(0, parent_size.y - y); + + wxWindow::DoSetSize(x, y, width, height, sizeFlags); +} + + +void wxAuiToolBar::OnIdle(wxIdleEvent& evt) +{ + DoIdleUpdate(); + evt.Skip(); +} + +void wxAuiToolBar::OnPaint(wxPaintEvent& WXUNUSED(evt)) +{ + wxBufferedPaintDC dc(this); + wxRect cli_rect(wxPoint(0,0), GetClientSize()); + + + bool horizontal = true; + if (m_style & wxAUI_TB_VERTICAL) + horizontal = false; + + + m_art->DrawBackground(dc, this, cli_rect); + + int gripper_size = m_art->GetElementSize(wxAUI_TBART_GRIPPER_SIZE); + int dropdown_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE); + + // paint the gripper + if (gripper_size > 0 && m_gripper_sizer_item) + { + wxRect gripper_rect = m_gripper_sizer_item->GetRect(); + if (horizontal) + gripper_rect.width = gripper_size; + else + gripper_rect.height = gripper_size; + 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_overflow_visible) + 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.sizer_item) + continue; + + wxRect item_rect = item.sizer_item->GetRect(); + + + if ((horizontal && item_rect.x + item_rect.width >= last_extent) || + (!horizontal && item_rect.y + item_rect.height >= last_extent)) + { + break; + } + + if (item.kind == wxITEM_SEPARATOR) + { + // draw a separator + m_art->DrawSeparator(dc, this, item_rect); + } + else if (item.kind == wxITEM_LABEL) + { + // draw a text label only + m_art->DrawLabel(dc, this, item, item_rect); + } + else if (item.kind == wxITEM_NORMAL) + { + // draw a regular button or dropdown button + if (!item.dropdown) + m_art->DrawButton(dc, this, item, item_rect); + else + m_art->DrawDropDownButton(dc, this, item, item_rect); + } + else if (item.kind == wxITEM_CHECK) + { + // draw a toggle button + m_art->DrawButton(dc, this, item, item_rect); + } + else if (item.kind == wxITEM_CONTROL) + { + // draw the control's label + m_art->DrawControlLabel(dc, this, item, item_rect); + } + + // 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_overflow_sizer_item) + { + wxRect dropdown_rect = GetOverflowRect(); + m_art->DrawOverflowButton(dc, this, dropdown_rect, m_overflow_state); + } +} + +void wxAuiToolBar::OnEraseBackground(wxEraseEvent& WXUNUSED(evt)) +{ + // empty +} + +void wxAuiToolBar::OnLeftDown(wxMouseEvent& evt) +{ + wxRect cli_rect(wxPoint(0,0), GetClientSize()); + + if (m_gripper_sizer_item) + { + wxRect gripper_rect = m_gripper_sizer_item->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_overflow_sizer_item) + { + wxRect overflow_rect = GetOverflowRect(); + + if (m_art && + m_overflow_visible && + overflow_rect.Contains(evt.m_x, evt.m_y)) + { + wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_OVERFLOW_CLICK, -1); + e.SetEventObject(this); + e.SetToolId(-1); + e.SetClickPoint(wxPoint(evt.GetX(), evt.GetY())); + bool processed = ProcessEvent(e); + + if (processed) + { + DoIdleUpdate(); + } + else + { + size_t i, count; + wxAuiToolBarItemArray overflow_items; + + + // add custom overflow prepend items, if any + count = m_custom_overflow_prepend.GetCount(); + for (i = 0; i < count; ++i) + overflow_items.Add(m_custom_overflow_prepend[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_custom_overflow_append.GetCount(); + for (i = 0; i < count; ++i) + overflow_items.Add(m_custom_overflow_append[i]); + + int res = m_art->ShowDropDown(this, overflow_items); + m_overflow_state = 0; + Refresh(false); + if (res != -1) + { + wxCommandEvent e(wxEVT_COMMAND_MENU_SELECTED, res); + e.SetEventObject(this); + GetParent()->ProcessEvent(e); + } + } + + return; + } + } + + m_dragging = false; + m_action_pos = wxPoint(evt.GetX(), evt.GetY()); + m_action_item = FindToolByPosition(evt.GetX(), evt.GetY()); + + if (m_action_item) + { + if (m_action_item->state & wxAUI_BUTTON_STATE_DISABLED) + { + m_action_pos = wxPoint(-1,-1); + m_action_item = NULL; + return; + } + + SetPressedItem(m_action_item); + + // fire the tool dropdown event + wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_TOOL_DROPDOWN, m_action_item->id); + e.SetEventObject(this); + e.SetToolId(m_action_item->id); + e.SetDropDownClicked(false); + + int mouse_x = evt.GetX(); + wxRect rect = m_action_item->sizer_item->GetRect(); + + if (m_action_item->dropdown && + mouse_x >= (rect.x+rect.width-BUTTON_DROPDOWN_WIDTH-1) && + mouse_x < (rect.x+rect.width)) + { + e.SetDropDownClicked(true); + } + + e.SetClickPoint(evt.GetPosition()); + e.SetItemRect(rect); + ProcessEvent(e); + DoIdleUpdate(); + } +} + +void wxAuiToolBar::OnLeftUp(wxMouseEvent& evt) +{ + SetPressedItem(NULL); + + wxAuiToolBarItem* hit_item = FindToolByPosition(evt.GetX(), evt.GetY()); + if (hit_item && !(hit_item->state & wxAUI_BUTTON_STATE_DISABLED)) + { + SetHoverItem(hit_item); + } + + + if (m_dragging) + { + // reset drag and drop member variables + m_dragging = false; + m_action_pos = wxPoint(-1,-1); + m_action_item = NULL; + return; + } + else + { + wxAuiToolBarItem* hit_item; + hit_item = FindToolByPosition(evt.GetX(), evt.GetY()); + + if (m_action_item && hit_item == m_action_item) + { + SetToolTip(NULL); + + if (hit_item->kind == wxITEM_CHECK) + { + bool toggle = false; + + if (m_action_item->state & wxAUI_BUTTON_STATE_CHECKED) + toggle = false; + else + toggle = true; + + ToggleTool(m_action_item->id, toggle); + + wxCommandEvent e(wxEVT_COMMAND_MENU_SELECTED, m_action_item->id); + e.SetEventObject(this); + ProcessEvent(e); + DoIdleUpdate(); + } + else + { + wxCommandEvent e(wxEVT_COMMAND_MENU_SELECTED, m_action_item->id); + e.SetEventObject(this); + ProcessEvent(e); + DoIdleUpdate(); + } + } + } + + // reset drag and drop member variables + m_dragging = false; + m_action_pos = wxPoint(-1,-1); + m_action_item = NULL; +} + +void wxAuiToolBar::OnRightDown(wxMouseEvent& evt) +{ + wxRect cli_rect(wxPoint(0,0), GetClientSize()); + + if (m_gripper_sizer_item) + { + wxRect gripper_rect = m_gripper_sizer_item->GetRect(); + if (gripper_rect.Contains(evt.GetX(), evt.GetY())) + return; + } + + if (m_overflow_sizer_item) + { + int dropdown_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE); + if (dropdown_size > 0 && + evt.m_x > cli_rect.width - dropdown_size && + evt.m_y >= 0 && + evt.m_y < cli_rect.height && + m_art) + { + return; + } + } + + m_action_pos = wxPoint(evt.GetX(), evt.GetY()); + m_action_item = FindToolByPosition(evt.GetX(), evt.GetY()); + + if (m_action_item) + { + if (m_action_item->state & wxAUI_BUTTON_STATE_DISABLED) + { + m_action_pos = wxPoint(-1,-1); + m_action_item = NULL; + return; + } + } +} + +void wxAuiToolBar::OnRightUp(wxMouseEvent& evt) +{ + wxAuiToolBarItem* hit_item; + hit_item = FindToolByPosition(evt.GetX(), evt.GetY()); + + if (m_action_item && hit_item == m_action_item) + { + if (hit_item->kind == wxITEM_NORMAL) + { + wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, m_action_item->id); + e.SetEventObject(this); + e.SetToolId(m_action_item->id); + e.SetClickPoint(m_action_pos); + ProcessEvent(e); + DoIdleUpdate(); + } + } + else + { + // right-clicked on the invalid area of the toolbar + wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_RIGHT_CLICK, -1); + e.SetEventObject(this); + e.SetToolId(-1); + e.SetClickPoint(m_action_pos); + ProcessEvent(e); + DoIdleUpdate(); + } + + // reset member variables + m_action_pos = wxPoint(-1,-1); + m_action_item = NULL; +} + +void wxAuiToolBar::OnMiddleDown(wxMouseEvent& evt) +{ + wxRect cli_rect(wxPoint(0,0), GetClientSize()); + + if (m_gripper_sizer_item) + { + wxRect gripper_rect = m_gripper_sizer_item->GetRect(); + if (gripper_rect.Contains(evt.GetX(), evt.GetY())) + return; + } + + if (m_overflow_sizer_item) + { + int dropdown_size = m_art->GetElementSize(wxAUI_TBART_OVERFLOW_SIZE); + if (dropdown_size > 0 && + evt.m_x > cli_rect.width - dropdown_size && + evt.m_y >= 0 && + evt.m_y < cli_rect.height && + m_art) + { + return; + } + } + + m_action_pos = wxPoint(evt.GetX(), evt.GetY()); + m_action_item = FindToolByPosition(evt.GetX(), evt.GetY()); + + if (m_action_item) + { + if (m_action_item->state & wxAUI_BUTTON_STATE_DISABLED) + { + m_action_pos = wxPoint(-1,-1); + m_action_item = NULL; + return; + } + } +} + +void wxAuiToolBar::OnMiddleUp(wxMouseEvent& evt) +{ + wxAuiToolBarItem* hit_item; + hit_item = FindToolByPosition(evt.GetX(), evt.GetY()); + + if (m_action_item && hit_item == m_action_item) + { + if (hit_item->kind == wxITEM_NORMAL) + { + wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_MIDDLE_CLICK, m_action_item->id); + e.SetEventObject(this); + e.SetToolId(m_action_item->id); + e.SetClickPoint(m_action_pos); + ProcessEvent(e); + DoIdleUpdate(); + } + } + + // reset member variables + m_action_pos = wxPoint(-1,-1); + m_action_item = NULL; +} + +void wxAuiToolBar::OnMotion(wxMouseEvent& evt) +{ + // start a drag event + if (!m_dragging && + m_action_item != NULL && + m_action_pos != wxPoint(-1,-1) && + abs(evt.m_x - m_action_pos.x) + abs(evt.m_y - m_action_pos.y) > 5) + { + SetToolTip(NULL); + + m_dragging = true; + + wxAuiToolBarEvent e(wxEVT_COMMAND_AUITOOLBAR_BEGIN_DRAG, GetId()); + e.SetEventObject(this); + e.SetToolId(m_action_item->id); + ProcessEvent(e); + DoIdleUpdate(); + return; + } + + wxAuiToolBarItem* hit_item = FindToolByPosition(evt.GetX(), evt.GetY()); + if (hit_item) + { + if (!(hit_item->state & wxAUI_BUTTON_STATE_DISABLED)) + SetHoverItem(hit_item); + else + SetHoverItem(NULL); + } + else + { + // no hit item, remove any hit item + SetHoverItem(hit_item); + } + + // figure out tooltips + wxAuiToolBarItem* packing_hit_item; + packing_hit_item = FindToolByPositionWithPacking(evt.GetX(), evt.GetY()); + if (packing_hit_item) + { + if (packing_hit_item != m_tip_item) + { + m_tip_item = packing_hit_item; + + if (packing_hit_item->short_help.Length() > 0) + SetToolTip(packing_hit_item->short_help); + else + SetToolTip(NULL); + } + } + else + { + SetToolTip(NULL); + m_tip_item = NULL; + } + + // if we've pressed down an item and we're hovering + // over it, make sure it's state is set to pressed + if (m_action_item) + { + if (m_action_item == hit_item) + SetPressedItem(m_action_item); + else + SetPressedItem(NULL); + } + + // figure out the dropdown button state (are we hovering or pressing it?) + RefreshOverflowState(); +} + +void wxAuiToolBar::OnLeaveWindow(wxMouseEvent& WXUNUSED(evt)) +{ + RefreshOverflowState(); + SetHoverItem(NULL); + SetPressedItem(NULL); + + m_tip_item = NULL; +} + + +void wxAuiToolBar::OnSetCursor(wxSetCursorEvent& evt) +{ + wxCursor cursor = wxNullCursor; + + if (m_gripper_sizer_item) + { + wxRect gripper_rect = m_gripper_sizer_item->GetRect(); + if (gripper_rect.Contains(evt.GetX(), evt.GetY())) + { + cursor = wxCursor(wxCURSOR_SIZING); + } + } + + evt.SetCursor(cursor); +} + + +#endif // wxUSE_AUI + diff --git a/src/aui/framemanager.cpp b/src/aui/framemanager.cpp index 8d0ce8eaa2..8961b4f86e 100644 --- a/src/aui/framemanager.cpp +++ b/src/aui/framemanager.cpp @@ -29,6 +29,7 @@ #include "wx/aui/dockart.h" #include "wx/aui/floatpane.h" #include "wx/aui/tabmdi.h" +#include "wx/aui/auibar.h" #ifndef WX_PRECOMP #include "wx/panel.h" @@ -1006,6 +1007,22 @@ bool wxAuiManager::AddPane(wxWindow* window, const wxAuiPaneInfo& pane_info) button.button_id = wxAUI_BUTTON_CLOSE; pinfo.buttons.Add(button); } + + if (pinfo.HasGripper()) + { + if (pinfo.window->IsKindOf(CLASSINFO(wxAuiToolBar))) + { + // prevent duplicate gripper -- both wxAuiManager and wxAuiToolBar + // have a gripper control. The toolbar's built-in gripper + // meshes better with the look and feel of the control than ours, + // so turn wxAuiManager's gripper off, and the toolbar's on. + + wxAuiToolBar* tb = static_cast(pinfo.window); + pinfo.SetFlag(wxAuiPaneInfo::optionGripper, false); + tb->SetGripperVisible(true); + } + } + if (pinfo.best_size == wxDefaultSize && pinfo.window) @@ -1037,6 +1054,8 @@ bool wxAuiManager::AddPane(wxWindow* window, const wxAuiPaneInfo& pane_info) } } + + return true; } @@ -3572,7 +3591,6 @@ void wxAuiManager::OnFloatingPaneMoved(wxWindow* wnd, wxDirection dir) wxPoint frame_pos = pane.frame->GetPosition(); wxPoint action_offset(pt.x-frame_pos.x, pt.y-frame_pos.y); - // if a key modifier is pressed while dragging the frame, // don't dock the window if (CanDockPanel(pane)) -- 2.45.2