diff --git a/clientgui/common/wxFNBDropTarget.h b/clientgui/common/wxFNBDropTarget.h new file mode 100644 index 0000000000..29c4560b4e --- /dev/null +++ b/clientgui/common/wxFNBDropTarget.h @@ -0,0 +1,78 @@ +#ifndef _WX_FNB_DROP_TARGET_H +#define _WX_FNB_DROP_TARGET_H + +#include +#include + +/** +\brief Contains the information about dragged page (page index and container). +*/ +class wxFNBDragInfo +{ + wxWindow * m_Container; + int m_PageIndex; +public: + /** + Constructor + \param container - pointer to wxPageContainer object which contains dragged page + \param pageindex - index of dragged page + */ + wxFNBDragInfo(wxWindow * container, int pageindex) : m_Container(container), m_PageIndex(pageindex){} + /** + Returns wxPageContainer object which contains dragged page + */ + wxWindow * GetContainer() {return m_Container;} + /** + Returns the index of dragged page + */ + int GetPageIndex() {return m_PageIndex;} +}; + +/** +\brief Used for processing drag-n-drop opeartions +*/ +template +class wxFNBDropTarget : public wxDropTarget +{ +private: + typedef wxDragResult (T::*pt2Func)(wxCoord, wxCoord, int, wxWindow *); + T* m_pParent; + pt2Func m_pt2CallbackFunc; + wxCustomDataObject * m_DataObject; +public: + /** + \brief Constructor + \param pParent - Object that will handle drag-n-drop operation + \param pt2CallbackFunc - Pointer to callback method which should be called after dragging the notebook page + */ + wxFNBDropTarget(T* pParent, pt2Func pt2CallbackFunc) + : m_pParent(pParent) + , m_pt2CallbackFunc(pt2CallbackFunc) + , m_DataObject(NULL) + { + m_DataObject = new wxCustomDataObject(wxDataFormat(wxT("wxFNB"))); + SetDataObject(m_DataObject); + } + /** + \brief Virtual Destructor + */ + virtual ~wxFNBDropTarget(void) {} + /** + \brief Used for processing drop operation + \param x - X-coordinate + \param y - Y-coordinate + \param def - Result of drag-n-drop operation + */ + virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def) + { + GetData(); + wxFNBDragInfo * draginfo = (wxFNBDragInfo *)m_DataObject->GetData(); + if(!draginfo) + { + return wxDragNone; + } + return (m_pParent->*m_pt2CallbackFunc)(x, y, draginfo->GetPageIndex(), (T *)draginfo->GetContainer()); + } +}; + +#endif diff --git a/clientgui/common/wxFlatNotebook.cpp b/clientgui/common/wxFlatNotebook.cpp new file mode 100644 index 0000000000..fba4521d73 --- /dev/null +++ b/clientgui/common/wxFlatNotebook.cpp @@ -0,0 +1,2188 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wxFlatNotebook.cpp +// Purpose: generic implementation of flat style notebook class. +// Author: Eran Ifrah +// Modified by: Priyank Bolia +// Created: 30/12/2005 +// Modified: 01/01/2006 +// Copyright: Eran Ifrah (c) +// Licence: wxWindows license +/////////////////////////////////////////////////////////////////////////////// + + +#include +#include +#include +#include + +IMPLEMENT_DYNAMIC_CLASS(wxFlatNotebookEvent, wxNotifyEvent) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CHANGED) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CHANGING) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CLOSING) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_FLATNOTEBOOK_CONTEXT_MENU) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CLOSED) + +IMPLEMENT_DYNAMIC_CLASS(wxFlatNotebookBase, wxPanel) + +BEGIN_EVENT_TABLE(wxFlatNotebookBase, wxPanel) +EVT_NAVIGATION_KEY(wxFlatNotebookBase::OnNavigationKey) +END_EVENT_TABLE() + +wxFlatNotebookBase::wxFlatNotebookBase(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) +{ + m_bForceSelection = false; + m_nPadding = 6; + m_nFrom = 0; + style |= wxTAB_TRAVERSAL; + m_pages = NULL; + wxPanel::Create(parent, id, pos, size, style, name); + + m_pages = new wxPageContainerBase(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, style); +} + +wxFlatNotebookBase::~wxFlatNotebookBase(void) +{ +} + +void wxFlatNotebookBase::Init() +{ + long style = GetWindowStyleFlag(); + m_pages->m_colorBorder = style & wxFNB_FANCY_TABS ? m_pages->m_colorTo : wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); + + m_mainSizer = new wxBoxSizer(wxVERTICAL); + SetSizer(m_mainSizer); + + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE)); + + // Add the tab container to the sizer + m_mainSizer->Insert(0, m_pages, 0, wxEXPAND); + + // Set default page height + wxClientDC dc(this); + int width, height; + wxString stam = wxT("Tp"); // Temp data to get the text height; + dc.GetTextExtent(stam, &width, &height); + + int tabHeight = height + 8; // We use 8 pixels as padding + m_pages->SetSizeHints(wxSize(-1, tabHeight)); + + m_pages->m_nFrom = m_nFrom; + m_pDropTarget = new wxFNBDropTarget(this, &wxFlatNotebookBase::OnDropTarget); + SetDropTarget(m_pDropTarget); +} + +wxPageContainerBase* wxFlatNotebookBase::CreatePageContainer() +{ + return new wxPageContainerBase(this, wxID_ANY); +} + +void wxFlatNotebookBase::SetActiveTabTextColour(const wxColour& textColour) +{ + m_pages->m_activeTextColor = textColour; +} + +wxDragResult wxFlatNotebookBase::OnDropTarget(wxCoord x, wxCoord y, int nTabPage, wxWindow * wnd_oldContainer) +{ + return m_pages->OnDropTarget(x, y, nTabPage, wnd_oldContainer); +} + +void wxFlatNotebookBase::AddPage(wxWindow* window, const wxString& caption, const bool selected, const int imgindex) +{ + // sanity check + if (!window) + return; + + // reparent the window to us + window->Reparent(this); + + // Add tab + bool bSelected = selected || m_windows.empty(); + int curSel = m_pages->GetSelection(); + + if( !m_pages->IsShown() ) + m_pages->Show(); + + m_pages->AddPage(caption, bSelected, imgindex); + m_windows.push_back(window); + + Freeze(); + + // Check if a new selection was made + if(bSelected) + { + if(curSel >= 0) + { + // Remove the window from the main sizer + m_mainSizer->Detach(m_windows[curSel]); + m_windows[curSel]->Hide(); + } + if(m_windowStyle & wxFNB_BOTTOM) + { + m_mainSizer->Insert(0, window, 1, wxEXPAND); + } + else + { + // We leave a space of 1 pixel around the window + m_mainSizer->Add(window, 1, wxEXPAND); + } + } + else + { + // Hide the page + window->Hide(); + } + m_mainSizer->Layout(); + Thaw(); + Refresh(); + +} + +void wxFlatNotebookBase::SetImageList(wxFlatNotebookImageList * imglist) +{ + m_pages->SetImageList(imglist); +} + +wxFlatNotebookImageList * wxFlatNotebookBase::GetImageList() +{ + return m_pages->GetImageList(); +} + +bool wxFlatNotebookBase::InsertPage(size_t index, wxWindow* page, const wxString& text, bool select, const int imgindex) +{ + // sanity check + if (!page) + return false; + + // reparent the window to us + page->Reparent(this); + + if(m_windows.empty()) + { + AddPage(page, text, select, imgindex); + return true; + } + index = std::min((unsigned int)index, (unsigned int)m_windows.size()); + // Insert tab + bool bSelected = select || m_windows.empty(); + int curSel = m_pages->GetSelection(); + + if(index <= m_windows.size()) + { + std::vector::iterator iter = m_windows.begin() + index; + m_windows.insert(iter, page); + wxLogTrace(wxTraceMask(), _("New page inserted. Index = %i"), index); + } + else + { + m_windows.push_back(page); + wxLogTrace(wxTraceMask(), _("New page appended. Index = %i"), index); + } + m_pages->InsertPage(index, page, text, bSelected, imgindex); + if((int)index <= curSel) curSel++; + + Freeze(); + + // Check if a new selection was made + if(bSelected) + { + if(curSel >= 0) + { + // Remove the window from the main sizer + m_mainSizer->Detach(m_windows[curSel]); + m_windows[curSel]->Hide(); + } + m_pages->SetSelection(index); + } + else + { + // Hide the page + page->Hide(); + } + Thaw(); + m_mainSizer->Layout(); + Refresh(); + + return true; +} + +void wxFlatNotebookBase::SetSelection(size_t page) +{ + if(page >= m_windows.size()) + return; + + // Support for disabed tabs + if(!m_pages->GetEnabled(page) && m_windows.size() > 1 && !m_bForceSelection) + return; + + int curSel = m_pages->GetSelection(); + + // program allows the page change + Freeze(); + if(curSel >= 0) + { + // Remove the window from the main sizer + m_mainSizer->Detach(m_windows[curSel]); + m_windows[curSel]->Hide(); + } + + if(m_windowStyle & wxFNB_BOTTOM) + { + m_mainSizer->Insert(0, m_windows[page], 1, wxEXPAND); + } + else + { + // We leave a space of 1 pixel around the window + m_mainSizer->Add(m_windows[page], 1, wxEXPAND); + } + + m_windows[page]->Show(); + Thaw(); + + m_mainSizer->Layout(); + m_pages->m_iActivePage = (int)page; + m_pages->DoSetSelection(page); +} + +void wxFlatNotebookBase::DeletePage(size_t page) +{ + if(page >= m_windows.size()) + return; + + // Fire a closing event + wxFlatNotebookEvent event(wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CLOSING, GetId()); + event.SetSelection((int)page); + event.SetEventObject(this); + GetEventHandler()->ProcessEvent(event); + + // The event handler allows it? + if (!event.IsAllowed()) + return; + + Freeze(); + + // Delete the requested page + wxWindow *pageRemoved = m_windows[page]; + + // If the page is the current window, remove it from the sizer + // as well + if((int)page == m_pages->GetSelection()) + { + m_mainSizer->Detach(pageRemoved); + } + + // Remove it from the array as well + std::vector::iterator iter = std::find(m_windows.begin(), m_windows.end(), pageRemoved); + if(iter != m_windows.end()) + m_windows.erase(iter); + + // Now we can destroy it; in wxWidgets use Destroy instead of delete + pageRemoved->Destroy(); + + Thaw(); + + m_pages->DoDeletePage(page); + Refresh(); + + // Fire a closed event + wxFlatNotebookEvent closedEvent(wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CLOSED, GetId()); + closedEvent.SetSelection((int)page); + closedEvent.SetEventObject(this); + GetEventHandler()->ProcessEvent(closedEvent); +} + +bool wxFlatNotebookBase::DeleteAllPages() +{ + if(m_windows.empty()) + return false; + + Freeze(); + std::vector::iterator iter = m_windows.begin(); + for(; iter != m_windows.end(); iter++) + { + delete (*iter); + } + + m_windows.clear(); + + Thaw(); + + // Clear the container of the tabs as well + m_pages->DeleteAllPages(); + return true; +} + +wxWindow* wxFlatNotebookBase::GetCurrentPage() const +{ + int sel = m_pages->GetSelection(); + if(sel < 0) + return NULL; + + return m_windows[sel]; +} + +wxWindow* wxFlatNotebookBase::GetPage(size_t page) const +{ + if(page >= m_windows.size()) + return NULL; + + return m_windows[page]; +} + +int wxFlatNotebookBase::GetPageIndex(wxWindow* win) const +{ + for (size_t i = 0; i < m_windows.size(); ++i) + { + if (m_windows[i] == win) + return (int)i; + } + return -1; +} + +int wxFlatNotebookBase::GetSelection() const +{ + return m_pages->GetSelection(); +} + +void wxFlatNotebookBase::AdvanceSelection(bool bForward) +{ + m_pages->AdvanceSelection(bForward); +} + +int wxFlatNotebookBase::GetPageCount() const +{ + return (int)m_pages->GetPageCount(); +} + +void wxFlatNotebookBase::OnNavigationKey(wxNavigationKeyEvent& event) +{ + if ( event.IsWindowChange() ) + { + // change pages + AdvanceSelection(event.GetDirection()); + } + else + { + // pass to the parent + if ( GetParent() ) + { + event.SetCurrentFocus(this); + GetParent()->ProcessEvent(event); + } + } +} + +bool wxFlatNotebookBase::GetPageShapeAngle(int page_index, unsigned int * result) +{ + if(page_index < 0 || page_index >= (int)m_pages->m_pagesInfoVec.size()) return false; + *result = m_pages->m_pagesInfoVec[page_index].GetTabAngle(); + return true; +} + +void wxFlatNotebookBase::SetPageShapeAngle(int page_index, unsigned int angle) +{ + if(page_index < 0 || page_index >= (int)m_pages->m_pagesInfoVec.size()) return; + if(angle > 15) return; + + m_pages->m_pagesInfoVec[page_index].SetTabAngle(angle); +} + +void wxFlatNotebookBase::SetAllPagesShapeAngle(unsigned int angle) +{ + if(angle > 15) return; + for(unsigned int i = 0; i < m_pages->m_pagesInfoVec.size(); i++) + { + m_pages->m_pagesInfoVec[i].SetTabAngle(angle); + } + Refresh(); +} + +wxSize wxFlatNotebookBase::GetPageBestSize() +{ + return m_pages->GetClientSize(); +} + +bool wxFlatNotebookBase::SetPageText(size_t page, const wxString& text) +{ + bool bVal = m_pages->SetPageText(page, text); + m_pages->Refresh(); + return bVal; +} + +void wxFlatNotebookBase::SetPadding(const wxSize& padding) +{ + m_nPadding = padding.GetWidth(); +} + +void wxFlatNotebookBase::SetWindowStyleFlag(long style) +{ + wxPanel::SetWindowStyleFlag(style); + + if(m_pages) + { + // For changing the tab position (i.e. placing them top/bottom) + // refreshing the tab container is not enough + m_pages->m_colorBorder = style & wxFNB_FANCY_TABS ? m_pages->m_colorTo : wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); + SetSelection(m_pages->m_iActivePage); + } +} + +bool wxFlatNotebookBase::RemovePage(size_t page) +{ + if(page >= m_windows.size()) + return false; + + // Fire a closing event + wxFlatNotebookEvent event(wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CLOSING, GetId()); + event.SetSelection((int)page); + event.SetEventObject(this); + GetEventHandler()->ProcessEvent(event); + + // The event handler allows it? + if (!event.IsAllowed()) + return false; + + Freeze(); + + // Remove the requested page + wxWindow *pageRemoved = m_windows[page]; + + // If the page is the current window, remove it from the sizer + // as well + if((int)page == m_pages->GetSelection()) + { + m_mainSizer->Detach(pageRemoved); + } + + // Remove it from the array as well + std::vector::iterator iter = std::find(m_windows.begin(), m_windows.end(), pageRemoved); + if(iter != m_windows.end()) + m_windows.erase(iter); + + Thaw(); + + m_pages->DoDeletePage(page); + + return true; +} + +void wxFlatNotebookBase::SetRightClickMenu(wxMenu* menu) +{ + m_pages->m_pRightClickMenu = menu; +} + +wxString wxFlatNotebookBase::GetPageText(size_t page) +{ + return m_pages->GetPageText(page); +} + +void wxFlatNotebookBase::SetGradientColors(const wxColour& from, const wxColour& to, const wxColour& border) +{ + m_pages->m_colorFrom = from; + m_pages->m_colorTo = to; + m_pages->m_colorBorder = border; +} + +void wxFlatNotebookBase::SetGradientColorFrom(const wxColour& from) +{ + m_pages->m_colorFrom = from; +} + +void wxFlatNotebookBase::SetGradientColorTo(const wxColour& to) +{ + m_pages->m_colorTo = to; +} + +void wxFlatNotebookBase::SetGradientColorBorder(const wxColour& border) +{ + m_pages->m_colorBorder = border; +} + +/// Gets first gradient colour +const wxColour& wxFlatNotebookBase::GetGradientColorFrom() +{ + return m_pages->m_colorFrom; +} + +/// Gets second gradient colour +const wxColour& wxFlatNotebookBase::GetGradientColorTo() +{ + return m_pages->m_colorTo; +} + +/// Gets the tab border colour +const wxColour& wxFlatNotebookBase::SetGradientColorBorder() +{ + return m_pages->m_colorBorder; +} + +/// Get the active tab text +const wxColour& wxFlatNotebookBase::GetActiveTabTextColour() +{ + return m_pages->m_activeTextColor; +} + +void wxFlatNotebookBase::SetPageImageIndex(size_t page, int imgindex) +{ + m_pages->SetPageImageIndex(page, imgindex); +} + +int wxFlatNotebookBase::GetPageImageIndex(size_t page) +{ + return m_pages->GetPageImageIndex(page); +} + +bool wxFlatNotebookBase::GetEnabled(size_t page) +{ + return m_pages->GetEnabled(page); +} + +void wxFlatNotebookBase::Enable(size_t page, bool enabled) +{ + if(page >= m_windows.size()) + return; + + m_windows[page]->Enable(enabled); + m_pages->Enable(page, enabled); +} + +const wxColour& wxFlatNotebookBase::GetNonActiveTabTextColour() +{ + return m_pages->m_nonActiveTextColor; +} + +void wxFlatNotebookBase::SetNonActiveTabTextColour(const wxColour& color) +{ + m_pages->m_nonActiveTextColor = color; +} + +void wxFlatNotebookBase::SetTabAreaColour(const wxColour& color) +{ + m_pages->m_tabAreaColor = color; +} + +const wxColour& wxFlatNotebookBase::GetTabAreaColour() +{ + return m_pages->m_tabAreaColor; +} + +void wxFlatNotebookBase::SetActiveTabColour(const wxColour& color) +{ + m_pages->m_activeTabColor = color; +} + +const wxColour& wxFlatNotebookBase::GetActiveTabColour() +{ + return m_pages->m_activeTabColor; +} + +/////////////////////////////////////////////////////////////////////////////////////////// +// +// wxPageContainerBase +// +/////////////////////////////////////////////////////////////////////////////////////////// + +BEGIN_EVENT_TABLE(wxPageContainerBase, wxControl) +EVT_PAINT(wxPageContainerBase::OnPaint) +EVT_SIZE(wxPageContainerBase::OnSize) +EVT_LEFT_DOWN(wxPageContainerBase::OnLeftDown) +EVT_LEFT_UP(wxPageContainerBase::OnLeftUp) +EVT_RIGHT_DOWN(wxPageContainerBase::OnRightDown) +EVT_MIDDLE_DOWN(wxPageContainerBase::OnMiddleDown) +EVT_MOTION(wxPageContainerBase::OnMouseMove) +EVT_ERASE_BACKGROUND(wxPageContainerBase::OnEraseBackground) +EVT_LEAVE_WINDOW(wxPageContainerBase::OnMouseLeave) +EVT_ENTER_WINDOW(wxPageContainerBase::OnMouseEnterWindow) +END_EVENT_TABLE() + +wxPageContainerBase::wxPageContainerBase(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style) +: m_ImageList(NULL) +, m_iActivePage(-1) +, m_pDropTarget(NULL) +, m_nLeftClickZone(wxFNB_NOWHERE) +{ + m_pRightClickMenu = NULL; + m_nXButtonStatus = wxFNB_BTN_NONE; + m_pParent = parent; + m_nRightButtonStatus = wxFNB_BTN_NONE; + m_nLeftButtonStatus = wxFNB_BTN_NONE; + m_nTabXButtonStatus = wxFNB_BTN_NONE; + + m_colorTo = wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION)); + m_colorFrom = wxColor(*wxWHITE); + m_activeTabColor = wxColor(*wxWHITE); + m_activeTextColor = wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT)); + m_tabAreaColor = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE); + + wxWindow::Create(parent, id, pos, size, style | wxNO_BORDER | wxNO_FULL_REPAINT_ON_RESIZE); + + m_nonActiveTextColor = wxT("GREY"); + m_pDropTarget = new wxFNBDropTarget(this, &wxPageContainerBase::OnDropTarget); + SetDropTarget(m_pDropTarget); +} + +int wxPageContainerBase::GetButtonAreaWidth(void) +{ + int btnareawidth; + long style = GetParent()->GetWindowStyleFlag(); + btnareawidth = ((wxFlatNotebookBase *)m_pParent)->m_nPadding * 2; + + if ((style & wxFNB_NO_X_BUTTON) == 0) + btnareawidth += BUTTON_SPACE; + + if ((style & wxFNB_NO_NAV_BUTTONS) == 0) + btnareawidth += BUTTON_SPACE*2; + + return btnareawidth; +} + +wxPageContainerBase::~wxPageContainerBase(void) +{ + if(m_pRightClickMenu) + { + delete m_pRightClickMenu; + m_pRightClickMenu = NULL; + } +} + +void wxPageContainerBase::OnPaint(wxPaintEvent &event) +{ + wxBufferedPaintDC dc(this); + if(m_pagesInfoVec.empty() || m_nFrom >= (int)m_pagesInfoVec.size()) + { + Hide(); + event.Skip(); + return; + } + + // Get the text hight + int height, width, tabHeight; + long style = GetParent()->GetWindowStyleFlag(); + wxString stam = wxT("Tp"); // Temp data to get the text height; + dc.GetTextExtent(stam, &width, &height); + + tabHeight = height + 8; // We use 8 pixels as padding + + // Calculate the number of rows required for drawing the tabs + wxRect rect = GetClientRect(); + int clientWidth = rect.width; + + // Set the maximum client size + SetSizeHints(wxSize(GetButtonsAreaLength(), tabHeight)); + + // Set brushes, pens and fonts + wxFont normalFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + wxFont boldFont = normalFont; + boldFont.SetWeight(wxFONTWEIGHT_BOLD); + + wxPen borderPen = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW)); + + wxBrush backBrush; + if(style & wxFNB_VC71) + backBrush = wxBrush(wxColour(247, 243, 233)); + else + backBrush = wxBrush(m_tabAreaColor); + + wxBrush noselBrush = wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); + wxBrush selBrush = wxBrush(m_activeTabColor); + + wxSize size = GetSize(); + + // Background + dc.SetTextBackground(style & wxFNB_VC71 ? wxColour(247, 243, 233) : GetBackgroundColour()); + dc.SetTextForeground(m_activeTextColor); + dc.SetBrush(backBrush); + + // If border style is set, set the pen to be border pen + if(style & wxFNB_TABS_BORDER_SIMPLE) + dc.SetPen(borderPen); + else + dc.SetPen(*wxTRANSPARENT_PEN); + dc.DrawRectangle(0, 0, size.x, size.y); + + // We always draw the bottom/upper line of the tabs + // regradless the style + dc.SetPen(borderPen); + DrawTabsLine(dc, GetClientRect()); + + // Restore the pen + dc.SetPen(borderPen); + + if(style & wxFNB_VC71 && !(style & wxFNB_BOTTOM)) + { + wxPen pen = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); + pen.SetWidth(4); + dc.SetPen(pen); + dc.DrawLine(0, size.y, size.x, size.y); + + // Restore the pen + dc.SetPen(borderPen); + } + + // Draw labels + int pom; + dc.SetFont(boldFont); + int posx = ((wxFlatNotebookBase *)m_pParent)->m_nPadding; + int i = 0; + + // Update all the tabs from 0 to 'm_nFrom' to be non visible + for(i=0; im_nPadding * 2 + width; + int imageYCoord = style & wxFNB_BOTTOM ? 3 : 6; + + /// Style to add a small 'x' button on the top right + /// of the tab + if(style & wxFNB_X_ON_TAB && i == GetSelection()) + { + /// The xpm image that contains the 'x' button is 9 pixles + tabWidth += ((wxFlatNotebookBase *)m_pParent)->m_nPadding + 9; + } + + if(!(style & wxFNB_VC71) && !(style & wxFNB_FANCY_TABS)) + // Default style + tabWidth += 2 * shapePoints; + + bool hasImage = (m_ImageList != NULL && m_pagesInfoVec[i].GetImageIndex() != -1); + + // For VC71 style, we only add the icon size (16 pixels) + if(hasImage) + { + if( (style & wxFNB_VC71) || (style & wxFNB_FANCY_TABS)) + tabWidth += (16 + ((wxFlatNotebookBase*)m_pParent)->m_nPadding); + else + // Default style + tabWidth += (16 + ((wxFlatNotebookBase*)m_pParent)->m_nPadding) + shapePoints / 2; + } + + // Check if we can draw more + if(posx + tabWidth + GetButtonsAreaLength() >= clientWidth) + break; + + // By default we clean the tab region + m_pagesInfoVec[i].GetRegion().Clear(); + + // Clean the 'x' buttn on the tab + // 'Clean' rectanlge is a rectangle with width or height + // with values lower than or equal to 0 + m_pagesInfoVec[i].GetXRect().SetSize(wxSize(-1, -1)); + + // Draw the tab + if(style & wxFNB_FANCY_TABS) + DrawFancyTab(dc, posx, i, hasImage, tabWidth, tabHeight); + else if(style & wxFNB_VC71) + DrawVC71Tab(dc, posx, i, hasImage, tabWidth, tabHeight); + else + DrawStandardTab(dc, posx, i, hasImage, tabWidth, tabHeight); + + + // Text drawing offset from the left border of the + // rectangle + int textOffset; + + // The width of the images are 16 pixels + if(hasImage) + textOffset = ((wxFlatNotebookBase *)m_pParent)->m_nPadding * 2 + 16 + shapePoints / 2 ; + else + textOffset = ((wxFlatNotebookBase *)m_pParent)->m_nPadding + shapePoints / 2 ; + + if(i != GetSelection()) + { + // Set the text background to be like the vertical lines + dc.SetTextForeground(m_nonActiveTextColor); + } + + // Draw the image for the tab if any +#ifdef __WXMSW__ + imageYCoord = style & wxFNB_BOTTOM ? 3 : 6; +#else + imageYCoord = style & wxFNB_BOTTOM ? 3 : 10; +#endif + + if(hasImage) + { + int imageXOffset = textOffset - 16 - ((wxFlatNotebookBase *)m_pParent)->m_nPadding; + dc.DrawBitmap((*m_ImageList)[m_pagesInfoVec[i].GetImageIndex()], + posx + imageXOffset, imageYCoord, true); + } + + dc.DrawText(GetPageText(i), posx + textOffset, imageYCoord); + + int textWidth, textHeight; + dc.GetTextExtent(GetPageText(i), &textWidth, &textHeight); + + int tabCloseButtonXCoord = posx + textOffset + textWidth + ((wxFlatNotebookBase *)m_pParent)->m_nPadding; + /// From version 1.2 - a style to add 'x' button + /// on a tab + if(style & wxFNB_X_ON_TAB) + { + int tabCloseButtonYCoord = imageYCoord + 3; + wxRect x_rect(tabCloseButtonXCoord, tabCloseButtonYCoord, FNB::tab_x_size, FNB::tab_x_size); + DrawTabX(dc, x_rect, i); + } + + // Restore the text forground + dc.SetTextForeground(m_activeTextColor); + + // Update the tab position & size + m_pagesInfoVec[i].SetPosition(wxPoint(posx, VERTICAL_BORDER_PADDING)); + m_pagesInfoVec[i].SetSize(wxSize(tabWidth, tabHeight)); + + posx += tabWidth; + } + + // Update all tabs that can not fit into the screen as non-visible + for(; i<(int)m_pagesInfoVec.size(); i++) + { + m_pagesInfoVec[i].SetPosition(wxPoint(-1, -1)); + m_pagesInfoVec[i].GetRegion().Clear(); + } + + // Draw the left/right/close buttons + // Left arrow + DrawLeftArrow(dc); + DrawRightArrow(dc); + DrawX(dc); +} + +// Tabs drawings +void wxPageContainerBase::DrawFancyTab(wxBufferedPaintDC& dc, + const int& posx, + const int &tabIdx, + const bool &hasImage, + const int &tabWidth, + const int &tabHeight) +{ + // Fancy tabs - like with VC71 but with the following differences: + // - The Selected tab is colored with gradient color + wxPen borderPen = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW)); + wxPen pen = (tabIdx==GetSelection()) ? wxPen(m_colorBorder) : wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); + long style = GetParent()->GetWindowStyleFlag(); + dc.SetPen(pen); + dc.SetBrush((tabIdx==GetSelection()) ? wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)) : wxBrush(wxColour(247, 243, 233))); + if(tabIdx == GetSelection()) + { + int posy = (style & wxFNB_BOTTOM) ? 0 : VERTICAL_BORDER_PADDING; + + wxRect rect(posx, posy, tabWidth, tabHeight); + FillGradientColor(dc, rect); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + pen.SetWidth(1); + dc.SetPen(pen); + + dc.DrawRectangle(rect); + pen.SetWidth(1); + dc.SetPen(pen); + } + else + { + // We dont draw a rectangle for non selected tabs, but only + // vertical line on the left + dc.SetPen(borderPen); + dc.DrawLine(posx + tabWidth, VERTICAL_BORDER_PADDING + 3, posx + tabWidth, tabHeight - 4); + } +} + +void wxPageContainerBase::DrawVC71Tab(wxBufferedPaintDC& dc, + const int& posx, + const int &tabIdx, + const bool &hasImage, + const int &tabWidth, + const int &tabHeight) +{ + // Visual studio 7.1 style + wxPen borderPen = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW)); + long style = GetParent()->GetWindowStyleFlag(); + + dc.SetPen((tabIdx==GetSelection()) ? wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)) : borderPen); + dc.SetBrush((tabIdx==GetSelection()) ? wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)) : wxBrush(wxColour(247, 243, 233))); + + if(tabIdx == GetSelection()) + { + int posy = (style & wxFNB_BOTTOM) ? 0 : VERTICAL_BORDER_PADDING; + dc.DrawRectangle(posx, posy, tabWidth, tabHeight); + + // Draw a black line on the left side of the + // rectangle + wxPen pen = wxPen(*wxBLACK); + dc.SetPen(pen); + + int blackLineHeight = (style & wxFNB_BOTTOM) ? VERTICAL_BORDER_PADDING + tabHeight - 3 : VERTICAL_BORDER_PADDING + tabHeight - 5; + dc.DrawLine(posx + tabWidth, (style & wxFNB_BOTTOM) ? 0 : VERTICAL_BORDER_PADDING, + posx + tabWidth, blackLineHeight - 1); + + // To give the tab more 3D look we do the following + // Incase the tab is on top, + // Draw a thik white line on topof the rectangle + // Otherwise, draw a thin (1 pixel) black line at the bottom + + pen = wxPen((style & wxFNB_BOTTOM) ? *wxBLACK : *wxWHITE); + pen.SetWidth((style & wxFNB_BOTTOM) ? 1 : 2); + dc.SetPen(pen); + int whiteLinePosY = (style & wxFNB_BOTTOM) ? blackLineHeight - 1: VERTICAL_BORDER_PADDING ; + dc.DrawLine(posx , whiteLinePosY, posx + tabWidth, whiteLinePosY); + } + else + { + // We dont draw a rectangle for non selected tabs, but only + // vertical line on the left + int blackLineHeight = (style & wxFNB_BOTTOM) ? tabHeight - 5 : VERTICAL_BORDER_PADDING + tabHeight - 8; + dc.DrawLine(posx + tabWidth, (style & wxFNB_BOTTOM) ? 3 : VERTICAL_BORDER_PADDING + 1, posx + tabWidth, blackLineHeight + 1); + } +} + + +void wxPageContainerBase::DrawStandardTab(wxBufferedPaintDC& dc, + const int& posx, + const int &tabIdx, + const bool &hasImage, + const int &tabWidth, + const int &tabHeight) +{ + // Default style + wxPen borderPen = wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW)); + long style = GetParent()->GetWindowStyleFlag(); + + wxPoint tabPoints[7]; + tabPoints[0].x = posx; + tabPoints[0].y = (style & wxFNB_BOTTOM) ? 0 : tabHeight; + + tabPoints[1].x = (int)(posx+(tabHeight-2)*tan((double)m_pagesInfoVec[tabIdx].GetTabAngle()/180.0*M_PI)); + tabPoints[1].y = (style & wxFNB_BOTTOM) ? tabHeight - (VERTICAL_BORDER_PADDING+2) : (VERTICAL_BORDER_PADDING+2); + + tabPoints[2].x = tabPoints[1].x+2; + tabPoints[2].y = (style & wxFNB_BOTTOM) ? tabHeight - VERTICAL_BORDER_PADDING : VERTICAL_BORDER_PADDING; + + tabPoints[3].x = (int)(posx+tabWidth-(tabHeight-2)*tan((double)m_pagesInfoVec[tabIdx].GetTabAngle()/180.0*M_PI))-2; + tabPoints[3].y = (style & wxFNB_BOTTOM) ? tabHeight - VERTICAL_BORDER_PADDING : VERTICAL_BORDER_PADDING; + + tabPoints[4].x = tabPoints[3].x+2; + tabPoints[4].y = (style & wxFNB_BOTTOM) ? tabHeight - (VERTICAL_BORDER_PADDING+2) : (VERTICAL_BORDER_PADDING+2); + + tabPoints[5].x = posx+tabWidth; + tabPoints[5].y = (style & wxFNB_BOTTOM) ? 0 : tabHeight; + + tabPoints[6].x = tabPoints[0].x; + tabPoints[6].y = tabPoints[0].y; + + if(tabIdx == GetSelection()) + { + // Draw the tab as rounded rectangle + dc.DrawPolygon(7, tabPoints); + } + else + { + if(tabIdx != GetSelection() - 1) + { + // Draw a vertical line to the right of the text + int pt1x, pt1y, pt2x, pt2y; + pt1x = tabPoints[5].x; + pt1y = (style & wxFNB_BOTTOM) ? 4 : tabHeight - 4; + pt2x = tabPoints[5].x; + pt2y = (style & wxFNB_BOTTOM) ? tabHeight - 4 : 4 ; + dc.DrawLine(pt1x, pt1y, pt2x, pt2y); + } + } + + if(style & wxFNB_BOTTOM && tabIdx == GetSelection()) + { + wxPen savePen = dc.GetPen(); + wxPen whitePen = wxPen(*wxWHITE); + whitePen.SetWidth(1); + dc.SetPen(whitePen); + + dc.DrawLine(tabPoints[0], tabPoints[5]); + + // Restore the pen + dc.SetPen(savePen); + } +} + +void wxPageContainerBase::AddPage(const wxString& caption, const bool selected, const int imgindex) +{ + if(selected) + { + m_iActivePage = (int)m_pagesInfoVec.size(); + } + m_pagesInfoVec.push_back(wxPageInfo(caption, imgindex)); + Refresh(); +} + +bool wxPageContainerBase::InsertPage(size_t index, wxWindow* /*page*/, const wxString& text, bool select, const int imgindex) +{ + if(select) + { + m_iActivePage = (int)m_pagesInfoVec.size(); + } + std::vector::iterator iter = m_pagesInfoVec.begin() + index; + m_pagesInfoVec.insert(iter, wxPageInfo(text, imgindex)); + Refresh(); + return true; +} + +void wxPageContainerBase::OnSize(wxSizeEvent& WXUNUSED(event)) +{ + Refresh(); // Call on paint +} + +void wxPageContainerBase::OnMiddleDown(wxMouseEvent& event) +{ + // Test if this style is enabled + long style = GetParent()->GetWindowStyleFlag(); + if(!(style & wxFNB_MOUSE_MIDDLE_CLOSES_TABS)) + return; + + wxPageInfo pgInfo; + int tabIdx; + int where = HitTest(event.GetPosition(), pgInfo, tabIdx); + switch(where) + { + case wxFNB_TAB: + { + DeletePage((size_t)tabIdx); + break; + } + default: + break; + } + event.Skip(); +} + +void wxPageContainerBase::OnRightDown(wxMouseEvent& event) +{ + if(m_pRightClickMenu) + { + wxPageInfo pgInfo; + int tabIdx; + int where = HitTest(event.GetPosition(), pgInfo, tabIdx); + switch(where) + { + case wxFNB_TAB: + case wxFNB_TAB_X: + { + if(!m_pagesInfoVec[tabIdx].GetEnabled()) + break; + + // Set the current tab to be active + SetSelection((size_t)tabIdx); + + // If the owner has defined a context menu for the tabs, + // popup the right click menu + if (m_pRightClickMenu) + PopupMenu(m_pRightClickMenu); + else + { + // send a message to popup a custom menu + wxFlatNotebookEvent event(wxEVT_COMMAND_FLATNOTEBOOK_CONTEXT_MENU, GetParent()->GetId()); + event.SetSelection((int)tabIdx); + event.SetOldSelection((int)m_iActivePage); + event.SetEventObject(GetParent()); + GetParent()->GetEventHandler()->ProcessEvent(event); + } + } + break; + default: + break; + } + } + event.Skip(); +} + +void wxPageContainerBase::OnLeftDown(wxMouseEvent& event) +{ + wxPageInfo pgInfo; + int tabIdx; + + // Reset buttons status + m_nXButtonStatus = wxFNB_BTN_NONE; + m_nLeftButtonStatus = wxFNB_BTN_NONE; + m_nRightButtonStatus = wxFNB_BTN_NONE; + m_nTabXButtonStatus = wxFNB_BTN_NONE; + + m_nLeftClickZone = HitTest(event.GetPosition(), pgInfo, tabIdx); + switch(m_nLeftClickZone) + { + case wxFNB_LEFT_ARROW: + m_nLeftButtonStatus = wxFNB_BTN_PRESSED; + Refresh(); + break; + case wxFNB_RIGHT_ARROW: + m_nRightButtonStatus = wxFNB_BTN_PRESSED; + Refresh(); + break; + case wxFNB_X: + m_nXButtonStatus = wxFNB_BTN_PRESSED; + Refresh(); + break; + case wxFNB_TAB_X: + m_nTabXButtonStatus = wxFNB_BTN_PRESSED; + Refresh(); + break; + case wxFNB_TAB: + { + if(m_iActivePage != tabIdx) + { + // Incase the tab is disabled, we dont allow to choose it + if(!m_pagesInfoVec[tabIdx].GetEnabled()) + break; + + int oldSelection = m_iActivePage; + + wxFlatNotebookEvent event(wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CHANGING, GetParent()->GetId()); + event.SetSelection((int)tabIdx); + event.SetOldSelection((int)oldSelection); + event.SetEventObject(GetParent()); + if(!GetParent()->GetEventHandler()->ProcessEvent(event) || event.IsAllowed()) + { + SetSelection(tabIdx); + + // Fire a wxEVT_COMMAND_TABBEDCTRL_PAGE_CHANGED event + event.SetEventType(wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CHANGED); + event.SetOldSelection((int)oldSelection); + GetParent()->GetEventHandler()->ProcessEvent(event); + } + } + break; + } + } +} + +void wxPageContainerBase::OnLeftUp(wxMouseEvent& event) +{ + wxPageInfo pgInfo; + int tabIdx; + + // forget the zone that was initially clicked + m_nLeftClickZone = wxFNB_NOWHERE; + + int where = HitTest(event.GetPosition(), pgInfo, tabIdx); + switch(where) + { + case wxFNB_LEFT_ARROW: + { + if(m_nFrom == 0) + break; + + // Make sure that the button was pressed before + if(m_nLeftButtonStatus != wxFNB_BTN_PRESSED) + break; + + m_nLeftButtonStatus = wxFNB_BTN_HOVER; + + // We scroll left with bulks of 5 + int scrollLeft = GetNumTabsCanScrollLeft(); + + m_nFrom -= scrollLeft; + if(m_nFrom < 0) + m_nFrom = 0; + + Refresh(); + break; + } + case wxFNB_RIGHT_ARROW: + { + if(m_nFrom >= (int)m_pagesInfoVec.size() - 1) + break; + + // Make sure that the button was pressed before + if(m_nRightButtonStatus != wxFNB_BTN_PRESSED) + break; + + m_nRightButtonStatus = wxFNB_BTN_HOVER; + + // Check if the right most tab is visible, if it is + // don't rotate right anymore + if(m_pagesInfoVec[m_pagesInfoVec.size()-1].GetPosition() != wxPoint(-1, -1)) + break; + + int lastVisibleTab = GetLastVisibleTab(); + if(lastVisibleTab < 0) + { + // Probably the screen is too small for displaying even a single + // tab, in this case we do nothing + break; + } + + m_nFrom += GetNumOfVisibleTabs(); + Refresh(); + break; + } + case wxFNB_X: + { + // Make sure that the button was pressed before + if(m_nXButtonStatus != wxFNB_BTN_PRESSED) + break; + + m_nXButtonStatus = wxFNB_BTN_HOVER; + + DeletePage((size_t)m_iActivePage); + break; + } + case wxFNB_TAB_X: + { + // Make sure that the button was pressed before + if(m_nTabXButtonStatus != wxFNB_BTN_PRESSED) + break; + + m_nTabXButtonStatus = wxFNB_BTN_HOVER; + + DeletePage((size_t)m_iActivePage); + break; + } + + } +} + +int wxPageContainerBase::HitTest(const wxPoint& pt, wxPageInfo& pageInfo, int &tabIdx) +{ + wxRect rect = GetClientRect(); + int btnLeftPos = GetLeftButtonPos(); + int btnRightPos = GetRightButtonPos(); + int btnXPos = GetXPos(); + long style = GetParent()->GetWindowStyleFlag(); + tabIdx = -1; + if(m_pagesInfoVec.empty()) + { + return wxFNB_NOWHERE; + } + + rect = wxRect(btnXPos, 5, 12, 12); + if(rect.Inside(pt)) + { + return (style & wxFNB_NO_X_BUTTON) ? wxFNB_NOWHERE : wxFNB_X; + } + + rect = wxRect(btnRightPos, 5, 12, 12); + if(rect.Inside(pt)) + { + return (style & wxFNB_NO_NAV_BUTTONS) ? wxFNB_NOWHERE : wxFNB_RIGHT_ARROW; + } + rect = wxRect(btnLeftPos, 5, 12, 12); + if(rect.Inside(pt)) + { + return (style & wxFNB_NO_NAV_BUTTONS) ? wxFNB_NOWHERE : wxFNB_LEFT_ARROW; + } + + // Test whether a left click was made on a tab + bool bFoundMatch = false; + for(size_t cur=m_nFrom; curSetSelection(page); + DoSetSelection(page); +} + +void wxPageContainerBase::DoSetSelection(size_t page) +{ + // Make sure that the selection is visible + long style = GetParent()->GetWindowStyleFlag(); + if(style & wxFNB_NO_NAV_BUTTONS) + { + // Incase that we dont have navigation buttons, + // there is no point of checking if the tab is visible + // Just do the refresh + Refresh(); + return; + } + + if(page < m_pagesInfoVec.size()) + { + //! fix for tabfocus + wxWindow* da_page = ((wxFlatNotebookBase *)m_pParent)->GetPage(page); + if ( da_page!=NULL ) + da_page->SetFocus(); + } + + if(!IsTabVisible(page)) + { + if(page == m_pagesInfoVec.size() - 1) + { + // Incase the added tab is last, + // the function IsTabVisible() will always return false + // and thus will cause an evil behaviour that the new + // tab will hide all other tabs, we need to check if the + // new selected tab can fit to the current screen + if(!CanFitToScreen(page)) + { + m_nFrom = (int)page; + } + Refresh(); + } + else + { + // Redraw the tabs starting from page + m_nFrom = (int)page; + Refresh(); + } + } +} + +void wxPageContainerBase::DeletePage(size_t page) +{ + wxFlatNotebookBase* book = (wxFlatNotebookBase*)GetParent(); + book->DeletePage(page); + book->Refresh(); +} + +bool wxPageContainerBase::IsTabVisible(size_t page) +{ + int iPage = (int)page; + int iLastVisiblePage = GetLastVisibleTab(); + + return iPage <= iLastVisiblePage && iPage >= m_nFrom; +} + +void wxPageContainerBase::DoDeletePage(size_t page) +{ + // Remove the page from the vector + wxFlatNotebookBase* book = (wxFlatNotebookBase*)GetParent(); + std::vector::iterator iter = m_pagesInfoVec.begin(); + std::vector::iterator endIter = m_pagesInfoVec.end(); + + m_pagesInfoVec.erase(iter + page); + + // Thanks to Yiaanis AKA Mandrav + if (m_iActivePage >= (int)page) + m_iActivePage--; + + // The delete page was the last first on the array, + // but the book still has more pages, so we set the + // active page to be the first one (0) + if(m_iActivePage < 0 && !m_pagesInfoVec.empty()) + m_iActivePage = 0; + + // Refresh the tabs + if(m_iActivePage >= 0) + { + book->m_bForceSelection = true; + book->SetSelection(m_iActivePage); + book->m_bForceSelection = false; + } + + if(m_pagesInfoVec.empty()) + { + // Erase the page container drawings + wxClientDC dc(this); + dc.Clear(); + } +} + +void wxPageContainerBase::DeleteAllPages() +{ + m_iActivePage = -1; + m_nFrom = 0; + m_pagesInfoVec.clear(); + + // Erase the page container drawings + wxClientDC dc(this); + dc.Clear(); +} + +void wxPageContainerBase::DrawTabX(wxDC& dc, const wxRect& rect, const int& tabIdx) +{ + long style = GetParent()->GetWindowStyleFlag(); + if(!(style & wxFNB_X_ON_TAB) || !CanDrawXOnTab()) + return; + + /// We draw the 'x' on the active tab only + if(tabIdx != GetSelection() || tabIdx < 0) + return; + + // Set the bitmap according to the button status + wxBitmap xBmp; + switch(m_nTabXButtonStatus) + { + case wxFNB_BTN_HOVER: + xBmp = wxBitmap(FNB::tab_x_button_hilite_xpm); + break; + case wxFNB_BTN_PRESSED: + xBmp = wxBitmap(FNB::tab_x_button_pressed_xpm); + break; + case wxFNB_BTN_NONE: + default: + xBmp = wxBitmap(FNB::tab_x_button_xpm); + break; + } + + /// Set the masking + xBmp.SetMask(new wxMask(xBmp, MASK_COLOR)); + + // Draw the new bitmap + dc.DrawBitmap(xBmp, rect.x, rect.y, true); + + // Update the vectpr + m_pagesInfoVec[tabIdx].SetXRect(rect); +} + +void wxPageContainerBase::DrawLeftArrow(wxDC& dc) +{ + long style = GetParent()->GetWindowStyleFlag(); + if(style & wxFNB_NO_NAV_BUTTONS) + return; + + // Make sure that there are pages in the container + if(m_pagesInfoVec.empty()) + return; + + wxRect rect = GetClientRect(); + int btnLeftPos = GetLeftButtonPos(); + rect = wxRect(btnLeftPos, 5, 16, 16); + + // Set the bitmap according to the button status + wxBitmap arrowBmp; + switch(m_nLeftButtonStatus) + { + case wxFNB_BTN_HOVER: + arrowBmp = wxBitmap(FNB::left_arrow_hilite_xpm); + break; + case wxFNB_BTN_PRESSED: + arrowBmp = wxBitmap(FNB::left_arrow_pressed_xpm); + break; + case wxFNB_BTN_NONE: + default: + arrowBmp = wxBitmap(FNB::left_arrow_xpm); + break; + } + + if(m_nFrom == 0) + { + // Handle disabled arrow + arrowBmp = wxBitmap(FNB::left_arrow_disabled_xpm); + } + + arrowBmp.SetMask(new wxMask(arrowBmp, MASK_COLOR)); + + // Erase old bitmap + wxPen pen = wxPen(style & wxFNB_VC71 ? wxColour(247, 243, 233) : m_tabAreaColor); + wxBrush brush = wxBrush(style & wxFNB_VC71 ? wxColour(247, 243, 233) :m_tabAreaColor); + pen.SetWidth(1); + dc.SetPen(pen); + dc.SetBrush(brush); + + dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height); + + // Draw the new bitmap + dc.DrawBitmap(arrowBmp, btnLeftPos, 5, true); +} + +void wxPageContainerBase::DrawRightArrow(wxDC& dc) +{ + long style = GetParent()->GetWindowStyleFlag(); + if(style & wxFNB_NO_NAV_BUTTONS) + return; + + // Make sure that there are pages in the container + if(m_pagesInfoVec.empty()) + return; + + wxRect rect = GetClientRect(); + int btnLeftPos = GetRightButtonPos(); + rect = wxRect(btnLeftPos, 5, 16, 16); + + // Set the bitmap according to the button status + wxBitmap arrowBmp; + switch(m_nRightButtonStatus) + { + case wxFNB_BTN_HOVER: + arrowBmp = wxBitmap(FNB::right_arrow_hilite_xpm); + break; + case wxFNB_BTN_PRESSED: + arrowBmp = wxBitmap(FNB::right_arrow_pressed_xpm); + break; + case wxFNB_BTN_NONE: + default: + arrowBmp = wxBitmap(FNB::right_arrow_xpm); + break; + } + + + // Check if the right most tab is visible, if it is + // don't rotate right anymore + if(m_pagesInfoVec[m_pagesInfoVec.size()-1].GetPosition() != wxPoint(-1, -1)) + { + arrowBmp = wxBitmap(FNB::right_arrow_disabled_xpm); + } + + arrowBmp.SetMask(new wxMask(arrowBmp, MASK_COLOR)); + + // Erase old bitmap + wxPen pen = wxPen(style & wxFNB_VC71 ? wxColour(247, 243, 233) : m_tabAreaColor); + wxBrush brush = wxBrush(style & wxFNB_VC71 ? wxColour(247, 243, 233) :m_tabAreaColor); + pen.SetWidth(1); + dc.SetPen(pen); + dc.SetBrush(brush); + + dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height); + + // Draw the new bitmap + dc.DrawBitmap(arrowBmp, btnLeftPos, 5, true); +} + +void wxPageContainerBase::DrawX(wxDC& dc) +{ + // Check if this style is enabled + long style = GetParent()->GetWindowStyleFlag(); + if(style & wxFNB_NO_X_BUTTON) + return; + + // Make sure that there are pages in the container + if(m_pagesInfoVec.empty()) + return; + + wxRect rect = GetClientRect(); + int btnLeftPos = GetXPos(); + rect = wxRect(btnLeftPos, 5, 16, 16); + + // Set the bitmap according to the button status + wxBitmap xbmp; + switch(m_nXButtonStatus) + { + case wxFNB_BTN_HOVER: + xbmp = wxBitmap(FNB::x_button_hilite_xpm); + break; + case wxFNB_BTN_PRESSED: + xbmp = wxBitmap(FNB::x_button_pressed_xpm); + break; + case wxFNB_BTN_NONE: + default: + xbmp = wxBitmap(FNB::x_button_xpm); + break; + } + + xbmp.SetMask(new wxMask(xbmp, MASK_COLOR)); + + // Erase old bitmap + wxPen pen = wxPen(style & wxFNB_VC71 ? wxColour(247, 243, 233) : m_tabAreaColor); + wxBrush brush = wxBrush(style & wxFNB_VC71 ? wxColour(247, 243, 233) : m_tabAreaColor); + pen.SetWidth(1); + dc.SetPen(pen); + dc.SetBrush(brush); + dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height); + + // Draw the new bitmap + dc.DrawBitmap(xbmp, btnLeftPos, 5, true); +} + +void wxPageContainerBase::OnMouseMove(wxMouseEvent& event) +{ + if (!m_pagesInfoVec.empty() && IsShown()) + { + const int xButtonStatus = m_nXButtonStatus; + const int xTabButtonStatus = m_nTabXButtonStatus; + const int rightButtonStatus = m_nRightButtonStatus; + const int leftButtonStatus = m_nLeftButtonStatus; + long style = GetParent()->GetWindowStyleFlag(); + + m_nXButtonStatus = wxFNB_BTN_NONE; + m_nRightButtonStatus = wxFNB_BTN_NONE; + m_nLeftButtonStatus = wxFNB_BTN_NONE; + m_nTabXButtonStatus = wxFNB_BTN_NONE; + + wxPageInfo pgInfo; + int tabIdx; + + switch(HitTest(event.GetPosition(), pgInfo, tabIdx)) + { + case wxFNB_X: + if (event.LeftIsDown()) + { + m_nXButtonStatus = (m_nLeftClickZone==wxFNB_X) ? wxFNB_BTN_PRESSED : wxFNB_BTN_NONE; + } + else + { + m_nXButtonStatus = wxFNB_BTN_HOVER; + } + break; + case wxFNB_TAB_X: + if (event.LeftIsDown()) + { + m_nTabXButtonStatus = (m_nLeftClickZone==wxFNB_TAB_X) ? wxFNB_BTN_PRESSED : wxFNB_BTN_NONE; + } + else + { + m_nTabXButtonStatus = wxFNB_BTN_HOVER; + } + break; + case wxFNB_RIGHT_ARROW: + if (event.LeftIsDown()) + { + m_nRightButtonStatus = (m_nLeftClickZone==wxFNB_RIGHT_ARROW) ? wxFNB_BTN_PRESSED : wxFNB_BTN_NONE; + } + else + { + m_nRightButtonStatus = wxFNB_BTN_HOVER; + } + break; + + case wxFNB_LEFT_ARROW: + if (event.LeftIsDown()) + { + m_nLeftButtonStatus = (m_nLeftClickZone==wxFNB_LEFT_ARROW) ? wxFNB_BTN_PRESSED : wxFNB_BTN_NONE; + } + else + { + m_nLeftButtonStatus = wxFNB_BTN_HOVER; + } + break; + + case wxFNB_TAB: + // Call virtual method for showing tooltip + ShowTabTooltip(tabIdx); + if(!GetEnabled((size_t)tabIdx)) + { + // Set the cursor to be 'No-entry' + ::wxSetCursor(wxCURSOR_NO_ENTRY); + } + if(event.LeftIsDown() && !(style & wxFNB_NODRAG)) + { + wxFNBDragInfo draginfo(this, tabIdx); + wxCustomDataObject dataobject(wxDataFormat(wxT("wxFNB"))); + dataobject.SetData(sizeof(wxFNBDragInfo), &draginfo); + wxDropSource dragSource(this); + dragSource.SetData(dataobject); + dragSource.DoDragDrop(wxDrag_DefaultMove); + } + break; + } + + const bool bRedrawX = m_nXButtonStatus != xButtonStatus; + const bool bRedrawRight = m_nRightButtonStatus != rightButtonStatus; + const bool bRedrawLeft = m_nLeftButtonStatus != leftButtonStatus; + const bool bRedrawTabX = m_nTabXButtonStatus != xTabButtonStatus; + + if (bRedrawX || bRedrawRight || bRedrawLeft || bRedrawTabX) + { + wxClientDC dc(this); + if (bRedrawX) + { + DrawX(dc); + } + if (bRedrawLeft) + { + DrawLeftArrow(dc); + } + if (bRedrawRight) + { + DrawRightArrow(dc); + } + if(bRedrawTabX) + { + DrawTabX(dc, pgInfo.GetXRect(), tabIdx); + } + } + } + event.Skip(); +} + +int wxPageContainerBase::GetLastVisibleTab() +{ + int i; + for(i=m_nFrom; i<(int)m_pagesInfoVec.size(); i++) + { + if(m_pagesInfoVec[i].GetPosition() == wxPoint(-1, -1)) + break; + } + return (i-1); +} + +int wxPageContainerBase::GetNumTabsCanScrollLeft() +{ + int i; + + // Reserved area for the buttons (<>x) + wxRect rect = GetClientRect(); + int clientWidth = rect.width; + int posx = ((wxFlatNotebookBase *)m_pParent)->m_nPadding, numTabs = 0, pom = 0, width, shapePoints, + height, tabHeight, tabWidth; + + wxClientDC dc(this); + + // Incase we have error prevent crash + if(m_nFrom < 0) + return 0; + + long style = GetParent()->GetWindowStyleFlag(); + for(i=m_nFrom; i>=0; i--) + { + wxFont boldFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + boldFont.SetWeight(wxFONTWEIGHT_BOLD); + dc.SetFont(boldFont); + + wxString stam = wxT("Tp"); // Temp data to get the text height; + dc.GetTextExtent(stam, &width, &height); + + tabHeight = height + 8; // We use 6 pixels as padding + if(style & wxFNB_VC71) + tabHeight = (style & wxFNB_BOTTOM) ? tabHeight - 4 : tabHeight; + else if(style & wxFNB_FANCY_TABS) + tabHeight = (style & wxFNB_BOTTOM) ? tabHeight - 3 : tabHeight; + + dc.GetTextExtent(GetPageText(i), &width, &pom); + if(style != wxFNB_VC71) + shapePoints = (int)(tabHeight*tan((double)m_pagesInfoVec[i].GetTabAngle()/180.0*M_PI)); + else + shapePoints = 0; + + tabWidth = ((wxFlatNotebookBase *)m_pParent)->m_nPadding * 2 + width; + if(!(style & wxFNB_VC71)) + // Default style + tabWidth += 2 * shapePoints; + + bool hasImage = (m_ImageList != NULL && m_pagesInfoVec[i].GetImageIndex() != -1); + + // For VC71 style, we only add the icon size (16 pixels) + if(hasImage) + { + if( !IsDefaultTabs() ) + tabWidth += (16 + ((wxFlatNotebookBase*)m_pParent)->m_nPadding); + else + // Default style + tabWidth += (16 + ((wxFlatNotebookBase*)m_pParent)->m_nPadding) + shapePoints / 2; + } + + if(posx + tabWidth + GetButtonsAreaLength() >= clientWidth) + break; + + numTabs++; + posx += tabWidth; + } + return numTabs; +} + +bool wxPageContainerBase::IsDefaultTabs() +{ + long style = GetParent()->GetWindowStyleFlag(); + bool res = (style & wxFNB_VC71) || (style & wxFNB_FANCY_TABS); + return !res; +} + +void wxPageContainerBase::AdvanceSelection(bool bForward) +{ + int nSel = GetSelection(); + + if(nSel < 0) + return; + + int nMax = (int)GetPageCount() - 1; + if ( bForward ) + SetSelection(nSel == nMax ? 0 : nSel + 1); + else + SetSelection(nSel == 0 ? nMax : nSel - 1); +} + + +void wxPageContainerBase::OnMouseLeave(wxMouseEvent& event) +{ + m_nLeftButtonStatus = wxFNB_BTN_NONE; + m_nXButtonStatus = wxFNB_BTN_NONE; + m_nRightButtonStatus = wxFNB_BTN_NONE; + m_nTabXButtonStatus = wxFNB_BTN_NONE; + + wxClientDC dc(this); + dc.BeginDrawing(); + + DrawX(dc); + DrawLeftArrow(dc); + DrawRightArrow(dc); + DrawTabX(dc, m_pagesInfoVec[GetSelection()].GetXRect(), GetSelection()); + dc.EndDrawing(); + event.Skip(); +} + +void wxPageContainerBase::OnMouseEnterWindow(wxMouseEvent& event) +{ + m_nLeftButtonStatus = wxFNB_BTN_NONE; + m_nXButtonStatus = wxFNB_BTN_NONE; + m_nRightButtonStatus = wxFNB_BTN_NONE; + m_nLeftClickZone = wxFNB_BTN_NONE; + + event.Skip(); +} + +void wxPageContainerBase::ShowTabTooltip(int tabIdx) +{ + wxWindow *pWindow = ((wxFlatNotebookBase *)m_pParent)->GetPage(tabIdx); + wxToolTip *pToolTip = pWindow->GetToolTip(); + if(pToolTip && pToolTip->GetWindow() == pWindow) + SetToolTip(pToolTip->GetTip()); +} + +void wxPageContainerBase::FillGradientColor(wxBufferedDC& dc, const wxRect& rect) +{ + // gradient fill from colour 1 to colour 2 with top to bottom + + if(rect.height < 1 || rect.width < 1) + return; + + int size = rect.height; + + // calculate gradient coefficients + long style = GetParent()->GetWindowStyleFlag(); + wxColour col2 = (style & wxFNB_BOTTOM) ? m_colorTo : m_colorFrom; + wxColour col1 = (style & wxFNB_BOTTOM) ? m_colorFrom : m_colorTo; + + double rstep = double((col2.Red() - col1.Red())) / double(size), rf = 0, + gstep = double((col2.Green() - col1.Green())) / double(size), gf = 0, + bstep = double((col2.Blue() - col1.Blue())) / double(size), bf = 0; + + wxColour currCol; + for(int y = rect.y; y < rect.y + size; y++) + { + currCol.Set( + (unsigned char)(col1.Red() + rf), + (unsigned char)(col1.Green() + gf), + (unsigned char)(col1.Blue() + bf) + ); + dc.SetBrush( wxBrush( currCol, wxSOLID ) ); + dc.SetPen(wxPen(currCol)); + dc.DrawLine(rect.x, y, rect.x + rect.width, y); + rf += rstep; gf += gstep; bf += bstep; + } +} + +void wxPageContainerBase::SetPageImageIndex(size_t page, int imgindex) +{ + if(page < m_pagesInfoVec.size()) + { + m_pagesInfoVec[page].SetImageIndex(imgindex); + Refresh(); + } +} + +int wxPageContainerBase::GetPageImageIndex(size_t page) +{ + if(page < m_pagesInfoVec.size()) + { + return m_pagesInfoVec[page].GetImageIndex(); + } + return -1; +} + +wxDragResult wxPageContainerBase::OnDropTarget(wxCoord x, wxCoord y, int nTabPage, wxWindow * wnd_oldContainer) +{ + // Disable drag'n'drop for disabled tab + if(!((wxPageContainerBase *)wnd_oldContainer)->m_pagesInfoVec[nTabPage].GetEnabled()) + return wxDragCancel; + + wxLogTrace(wxTraceMask(), _("Old Page Index = %i"), nTabPage); + wxPageContainerBase * oldContainer = (wxPageContainerBase *)wnd_oldContainer; + int nIndex = -1; + wxPageInfo pgInfo; + int where = HitTest(wxPoint(x, y), pgInfo, nIndex); + wxLogTrace(wxTraceMask(), _("OnDropTarget: index by HitTest = %i"), nIndex); + wxFlatNotebookBase * oldNotebook = (wxFlatNotebookBase *)oldContainer->GetParent(); + wxFlatNotebookBase * newNotebook = (wxFlatNotebookBase *)GetParent(); + + if(oldNotebook == newNotebook) + { + if(nTabPage >= 0) + { + switch(where) + { + case wxFNB_TAB: + MoveTabPage(nTabPage, nIndex); + break; + case wxFNB_NOWHERE: + MoveTabPage(nTabPage, GetLastVisibleTab()+1); + break; + default: + break; + } + } + } + else + { +#if defined(__WXMSW__) || defined(__WXGTK__) + if(nTabPage >= 0) + { + wxWindow * window = oldNotebook->GetPage(nTabPage); + if(window) + { + wxString caption = oldContainer->GetPageText(nTabPage); + int imageindex = oldContainer->GetPageImageIndex(nTabPage); + oldNotebook->RemovePage(nTabPage); + window->Reparent(newNotebook); + + newNotebook->InsertPage(nIndex, window, caption, true, imageindex); + } + } +#endif + } + return wxDragMove; +} + +void wxPageContainerBase::MoveTabPage(int nMove, int nMoveTo) +{ + if(nMove == nMoveTo) + return; + else if(nMoveTo < nMove) + nMoveTo++; + + // Remove the window from the main sizer + int nCurSel = ((wxFlatNotebookBase *)m_pParent)->m_pages->GetSelection(); + ((wxFlatNotebookBase *)m_pParent)->m_mainSizer->Detach(((wxFlatNotebookBase *)m_pParent)->m_windows[nCurSel]); + ((wxFlatNotebookBase *)m_pParent)->m_windows[nCurSel]->Hide(); + + wxWindow *pWindow = ((wxFlatNotebookBase *)m_pParent)->m_windows[nMove]; + ((wxFlatNotebookBase *)m_pParent)->m_windows.erase(((wxFlatNotebookBase *)m_pParent)->m_windows.begin() + nMove); + ((wxFlatNotebookBase *)m_pParent)->m_windows.insert(((wxFlatNotebookBase *)m_pParent)->m_windows.begin() + nMoveTo - 1, pWindow); + + wxPageInfo pgInfo = m_pagesInfoVec[nMove]; + m_pagesInfoVec.erase(m_pagesInfoVec.begin() + nMove); + m_pagesInfoVec.insert(m_pagesInfoVec.begin() + nMoveTo - 1, pgInfo); + + // Add the page according to the style + wxBoxSizer* pSizer = ((wxFlatNotebookBase *)m_pParent)->m_mainSizer; + long style = GetParent()->GetWindowStyleFlag(); + + + if(style & wxFNB_BOTTOM) + { + pSizer->Insert(0, pWindow, 1, wxEXPAND); + } + else + { + // We leave a space of 1 pixel around the window + pSizer->Add(pWindow, 1, wxEXPAND); + } + pWindow->Show(); + + pSizer->Layout(); + m_iActivePage = nMoveTo-1; + DoSetSelection(m_iActivePage); + Refresh(); +} + +bool wxPageContainerBase::CanFitToScreen(size_t page) +{ + // Incase the from is greater than page, + // we need to reset the m_nFrom, so in order + // to force the caller to do so, we return false + if(m_nFrom > (int)page) + return false; + + // Calculate the tab width including borders and image if any + wxClientDC dc(this); + + int width, pom, shapePoints, height, tabHeight; + long style = GetParent()->GetWindowStyleFlag(); + + wxString stam = wxT("Tp"); // Temp data to get the text height; + dc.GetTextExtent(stam, &width, &height); + dc.GetTextExtent(GetPageText(page), &width, &pom); + + tabHeight = height + 8; // We use 6 pixels as padding + + if(style & wxFNB_VC71) + tabHeight = (style & wxFNB_BOTTOM) ? tabHeight - 4 : tabHeight; + else if(style & wxFNB_FANCY_TABS) + tabHeight = (style & wxFNB_BOTTOM) ? tabHeight - 2 : tabHeight; + + int tabWidth = ((wxFlatNotebookBase *)m_pParent)->m_nPadding * 2 + width; + if(!(style & wxFNB_VC71)) + shapePoints = (int)(tabHeight*tan((double)m_pagesInfoVec[page].GetTabAngle()/180.0*M_PI)); + else + shapePoints = 0; + + if(!(style & wxFNB_VC71)) + // Default style + tabWidth += 2 * shapePoints; + + bool hasImage = (m_ImageList != NULL); + if(hasImage) hasImage &= m_pagesInfoVec[page].GetImageIndex() != -1; + + // For VC71 style, we only add the icon size (16 pixels) + if(hasImage && ( (style & wxFNB_VC71) || (style & wxFNB_FANCY_TABS)) ) + tabWidth += 16; + else + // Default style + tabWidth += 16 + shapePoints / 2; + + // Check if we can draw more + int posx = ((wxFlatNotebookBase *)m_pParent)->m_nPadding; + + if(m_nFrom >= 0) + { + for(int i=m_nFrom; i<(int)m_pagesInfoVec.size(); i++) + { + if(m_pagesInfoVec[i].GetPosition() == wxPoint(-1, -1)) + break; + posx += m_pagesInfoVec[i].GetSize().x; + } + } + + wxRect rect = GetClientRect(); + int clientWidth = rect.width; + + if(posx + tabWidth + GetButtonsAreaLength() >= clientWidth) + return false; + return true; +} + +int wxPageContainerBase::GetNumOfVisibleTabs() +{ + int i=m_nFrom; + int counter = 0; + for(; i<(int)m_pagesInfoVec.size(); i++, ++counter) + { + if(m_pagesInfoVec[i].GetPosition() == wxPoint(-1, -1)) + break; + } + return counter; +} + +bool wxPageContainerBase::GetEnabled(size_t page) +{ + if(page >= m_pagesInfoVec.size()) + return true; // Seems strange, but this is the default + return m_pagesInfoVec[page].GetEnabled(); +} + +void wxPageContainerBase::Enable(size_t page, bool enabled) +{ + if(page >= m_pagesInfoVec.size()) + return ; + return m_pagesInfoVec[page].Enable(enabled); +} + +int wxPageContainerBase::GetLeftButtonPos() +{ + long style = GetParent()->GetWindowStyleFlag(); + wxRect rect = GetClientRect(); + int clientWidth = rect.width; + if(style & wxFNB_NO_X_BUTTON) + return clientWidth - 38; + else + return clientWidth - 54; +} + +int wxPageContainerBase::GetRightButtonPos() +{ + long style = GetParent()->GetWindowStyleFlag(); + wxRect rect = GetClientRect(); + int clientWidth = rect.width; + if(style & wxFNB_NO_X_BUTTON) + return clientWidth - 22; + else + return clientWidth - 38; +} + +int wxPageContainerBase::GetXPos() +{ + long style = GetParent()->GetWindowStyleFlag(); + wxRect rect = GetClientRect(); + int clientWidth = rect.width; + if(style & wxFNB_NO_X_BUTTON) + return clientWidth; + else + return clientWidth - 22; +} + +int wxPageContainerBase::GetButtonsAreaLength() +{ + long style = GetParent()->GetWindowStyleFlag(); + if(style & wxFNB_NO_NAV_BUTTONS && style & wxFNB_NO_X_BUTTON) + return 0; + else if((style & wxFNB_NO_NAV_BUTTONS) && !(style & wxFNB_NO_X_BUTTON)) + return 53 - 16; + else if(!(style & wxFNB_NO_NAV_BUTTONS) && (style & wxFNB_NO_X_BUTTON)) + return 53 - 16; + else + // All buttons + return 53; +} + +void wxPageContainerBase::DrawTabsLine(wxDC& dc, const wxRect& rect) +{ + wxRect clientRect = rect; + long style = GetParent()->GetWindowStyleFlag(); + + dc.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNSHADOW))); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + dc.DrawRectangle(clientRect); + + if(!(style & wxFNB_TABS_BORDER_SIMPLE)) + { + dc.SetPen(wxPen(m_tabAreaColor)); + dc.DrawLine(0, 0, 0, clientRect.height); + if(style & wxFNB_BOTTOM) + dc.DrawLine(0, clientRect.height - 1, clientRect.width, clientRect.height - 1); + else + dc.DrawLine(0, 0, clientRect.width, 0); + dc.DrawLine(clientRect.width - 1, 0, clientRect.width - 1, clientRect.height); + } +} diff --git a/clientgui/common/wxFlatNotebook.h b/clientgui/common/wxFlatNotebook.h new file mode 100644 index 0000000000..1ccfe243d3 --- /dev/null +++ b/clientgui/common/wxFlatNotebook.h @@ -0,0 +1,1291 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wxFlatNotebook.cpp +// Purpose: generic implementation of flat style notebook class. +// Author: Eran Ifrah +// Modified by: Priyank Bolia +// Created: 30/12/2005 +// Modified: 01/01/2006 +// Copyright: Eran Ifrah (c) +// Licence: wxWindows license +/////////////////////////////////////////////////////////////////////////////// + +#ifndef WXFLATNOTEBOOK_H +#define WXFLATNOTEBOOK_H + +#include + +#ifdef __VISUALC__ +#pragma warning( push ) +#pragma warning(disable: 4702) +#endif + +#include + +#ifdef __VISUALC__ +#pragma warning(pop) +#endif + +#include +#include +#include + +#include + +class wxPageContainerBase; + +#ifndef M_PI +#define M_PI 3.14159265358979 +#endif + + +typedef std::vector wxFlatNotebookImageList; + + +/// wxFlatNotebookBase styles +#define wxFNB_DEFAULT_STYLE wxFNB_MOUSE_MIDDLE_CLOSES_TABS + +/// Use Visual Studio 2003 (VC7.1) Style for tabs +#define wxFNB_VC71 1 + +/// Use fancy style - square tabs filled with gradient coloring +#define wxFNB_FANCY_TABS 2 + +/// Draw thin border around the page +#define wxFNB_TABS_BORDER_SIMPLE 4 + +/// Do not display the 'X' button +#define wxFNB_NO_X_BUTTON 8 + +/// Do not display the Right / Left arrows +#define wxFNB_NO_NAV_BUTTONS 16 + +/// Use the mouse middle button for cloing tabs +#define wxFNB_MOUSE_MIDDLE_CLOSES_TABS 32 + +/// Place tabs at bottom - the default is to place them +/// at top +#define wxFNB_BOTTOM 64 + +/// Disable dragging of tabs +#define wxFNB_NODRAG 128 + +/// Disable dragging of tabs - Only available on the commercial version +#define wxFNB_VC8 256 + +/// Place 'X' on a tab +/// Note: This style is not supported on VC8 style +#define wxFNB_X_ON_TAB 512 + +#define VERTICAL_BORDER_PADDING 4 + +// Button size is a 16x16 xpm bitmap +#define BUTTON_SPACE 16 + +#define VC8_SHAPE_LEN 16 + +#define MASK_COLOR wxColor(0, 128, 128) + +class wxMenu; +/** +* \brief Nice cross-platform flat notebook with X-button :) +*/ + +class wxFlatNotebookBase : public wxPanel +{ +private: + friend class wxPageContainerBase; + +public: + + ///Default constructor + wxFlatNotebookBase(){} + /// Parametrized constructor + /** + \param parent - parent window + \param id - window ID + \param pos - window position + \param size - window size + \param style - window style + \param name - window class name + */ + wxFlatNotebookBase(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxT("Flat Notebook")); + + /// Destructor + ~wxFlatNotebookBase(void); + + /// Derived class should override this function to provide the + /// appropriate PageManager + virtual wxPageContainerBase* CreatePageContainer(); + + /// Advances the selection + /** + \param bForward - if set to true then selection should be advanced forward otherwise - backward + */ + void AdvanceSelection(bool bForward); + /// Apends new notebook page + /** + \param windows - window to be appended + \param caption - tab caption + \param selected - determines if new page should be selected automatically + \param imgindex - page image index + */ + void AddPage(wxWindow* windows, const wxString& caption, const bool selected = false, const int imgindex = -1); + /// Inserts new notebook page + /** + \param index - page index + \param page - window to be appended + \param text - tab caption + \param select - determines if new page should be selected automatically + \param imgindex - page image index + */ + bool InsertPage(size_t index, wxWindow* page, const wxString& text, bool select = false, const int imgindex = -1); + /// Changes the selection from currently visible/selected page to the page given by index. + /** + \param page - index of page to be selected + */ + void SetSelection(size_t page); + /// Removes the window from the notebook, and destroys the window associated with that notebook page. + /** + \param page - index of page to be deleted + */ + void DeletePage(size_t page); + + /// Deletes all notebook pages and destroys all windows associated with pages + bool DeleteAllPages(); + + /// Returns the total number of pages in the notebook. + int GetPageCount() const; + + /// Returns the window object associated with selected notebook page. + wxWindow * GetCurrentPage() const; + + /// Returns the window object associated with a notebook page. + /** + \param page - page index + */ + wxWindow * GetPage(size_t page) const; + /// Returns the page index of the window object. + /** + \param win - window object + */ + int GetPageIndex(wxWindow* win) const; + + /// Returns the currently visible/selected notebook page 0 based index. + int GetSelection() const; + /// Returns tab header inclination angle of specified page + /** + \param page_index - page index + \param result - pointer to the variable that receives the result + */ + bool GetPageShapeAngle(int page_index, unsigned int * result); + /// Sets tab header inclination angle of specified page + /** + \param page_index - page index + \param angle - new value of tab header inclination angle + */ + void SetPageShapeAngle(int page_index, unsigned int angle); + /// Sets tab header inclination angle for all pages + /** + \param angle - new value of tab header inclination angle + */ + void SetAllPagesShapeAngle(unsigned int angle); + + /// Returns the best size for a page + wxSize GetPageBestSize(); + + /// Sets the caption/text of the notebook page + /** + \param page - page index + \param text - new value of tab caption + */ + bool SetPageText(size_t page, const wxString& text); + + /// Removes the window from the notebook, but does not delete the associated window with that notebook page. + /** + \param page - page index to be removed + */ + bool RemovePage(size_t page); + + /// Sets the amount of space around each page's icon and label, in pixels. + /** + NB: The vertical padding cannot be changed in for wxFlatNotebookBase. + \param padding - new amount of space around each page's icon and label + */ + void SetPadding(const wxSize& padding); + /// Alters the notebook style + /** + \param style - new value of notebook style + */ + virtual void SetWindowStyleFlag(long style); + + /// Sets a right click menu to the notebook + /** + \param menu - right click menu object + */ + void SetRightClickMenu(wxMenu* menu); + /// Returns the page text + /** + \param page - page index + */ + wxString GetPageText(size_t page); + /// Sets an image index of specified page + /** + \param page - page index + \param imgindex - new image index + */ + void SetPageImageIndex(size_t page, int imgindex); + /// Returns an image index of specified page + /** + \param page - page index + */ + int GetPageImageIndex(size_t page); + /// Sets gradient colors (only applicable when using the wxFNB_FANCY_TABS) + /** + \param from - first gradient colour + \param to - second gradient colour + \param border - page border colour + */ + void SetGradientColors(const wxColour& from, const wxColour& to, const wxColour& border); + /// Sets first gradient colour + /** + \param from - new value of first gradient colour + */ + void SetGradientColorFrom(const wxColour& from); + + /// Sets second gradient colour + /** + \param to - new value of second gradient colour + */ + void SetGradientColorTo(const wxColour& to); + /// Sets the colour of page border + /** + \param border - new value of the colour of page border + */ + void SetGradientColorBorder(const wxColour& border); + /// Sets an image list associated with notebook pages + /** + \param imglist - image list object. + Image list assigned with this method will not be deleted by wxFlatNotebookBase's destructor, you must delete it yourself. + */ + void SetImageList(wxFlatNotebookImageList * imglist); + + /// Returns an image list object associated with wxFlatNotebookBase + wxFlatNotebookImageList * GetImageList(); + + /** + * \brief Drop event handler, to be passed as function pointer to CTextDropTarget class. + * \param x X coordinate where the drop take place + * \param y Y coordinate where the drop take place + * \param nTabPage page index + * \param wnd_oldContainer pointer to wxPageContainerBase object that contained dragged page + * \return Drag operation identifier + */ + wxDragResult OnDropTarget(wxCoord x, wxCoord y, int nTabPage, wxWindow * wnd_oldContainer); + + /// Enable / Disable page + /** + \param page - page to enable/diable + \param enabled - set to true to enable the tab, false otherwise + */ + void Enable(size_t page, bool enabled); + + /// Return Returns true if if the page is enabled + /** + \param page - page index + */ + bool GetEnabled(size_t page); + + /// Set the active tab text + /** + \param textColour - the active tab text colour + */ + void SetActiveTabTextColour(const wxColour& textColour); + + /// Gets first gradient colour + const wxColour& GetGradientColorFrom(); + + /// Gets second gradient colour + const wxColour& GetGradientColorTo(); + + /// Gets the tab border colour + const wxColour& SetGradientColorBorder(); + + /// Get the active tab text + const wxColour& GetActiveTabTextColour(); + + /// Get the non-active tab text color + const wxColour& GetNonActiveTabTextColour(); + + /// Set the non-active tab text color + void SetNonActiveTabTextColour(const wxColour& color); + + /// Return the tab area panel + wxPanel* GetTabArea() { return (wxPanel*)m_pages; } + + /// Get the tab area background colour + const wxColour& GetTabAreaColour(); + + /// Set the tab area background colour + void SetTabAreaColour(const wxColour& color); + + /// Get the active tab color + const wxColour& GetActiveTabColour(); + + /// Set the active tab color + void SetActiveTabColour(const wxColour& color); + + int GetPadding() { return m_nPadding; } +protected: + /// Initialization function, called internally + virtual void Init(); + wxPageContainerBase *m_pages; + +private: + /// Internal flag to force selection of page, + /// even if this page is disabled. + /// used incase such that the book itself need to update its selection. + /// e.g. after DeletePage() + bool m_bForceSelection; + + wxBoxSizer* m_mainSizer; + + /// vector of all the windows associated with the notebook pages. + std::vector m_windows; + wxFNBDropTarget *m_pDropTarget; + int m_nFrom; + int m_nPadding; + + DECLARE_DYNAMIC_CLASS(wxFlatNotebookBase) + DECLARE_EVENT_TABLE() + void OnNavigationKey(wxNavigationKeyEvent& event); +}; + +/** +* \brief Contains parameters of notebook page +*/ +class wxPageInfo +{ +private: + // Members + /// Page caption + wxString m_strCaption; + + /// Page position + wxPoint m_pos; + + /// Page size + wxSize m_size; + + /// Page region + wxRegion m_region; + + /// Angle for painting tab + unsigned int m_TabAngle; + + /// Page image index + int m_ImageIndex; + + /// Page enable/disabled flag + bool m_bEnabled; + + /// Tab 'x' button rectangle + wxRect m_xRect; + +public: + + /// Default constructor + wxPageInfo(): m_strCaption(wxEmptyString), m_TabAngle(0), m_ImageIndex(-1), m_bEnabled(true){}; + /// Parametrized constructor + /** + \param caption - page caption + \param imgindex - image index + */ + wxPageInfo(const wxString& caption, int imgindex) : + m_strCaption(caption), m_pos(-1, -1), m_size(-1, -1), m_TabAngle(0), m_ImageIndex(imgindex), m_bEnabled(true){} + /// Destructor + ~wxPageInfo(){}; + + /// Sets page caption + /** + \param value - new page caption + */ + void SetCaption(wxString value) {m_strCaption = value;} + + ///Returns page caption + wxString GetCaption() {return m_strCaption;} + + /// Sets page position + /** + \param value - new page position + */ + void SetPosition(wxPoint value) {m_pos = value;} + + ///Returns page position + const wxPoint & GetPosition() {return m_pos;} + + /// Sets page size + /** + \param value - new page size + */ + void SetSize(wxSize value) {m_size = value;} + + ///Returns page size + const wxSize & GetSize() {return m_size;} + + /// Sets the tab header inclination angle + /** + \param value - new tab header inclination angle + */ + void SetTabAngle(unsigned int value) {m_TabAngle = std::min((unsigned int)(45), (unsigned int)(value));} + + /// Returns an inclination of tab header borders + unsigned int GetTabAngle() {return m_TabAngle;} + /// Sets page image index + /** + \param value - new image index + */ + void SetImageIndex(int value) {m_ImageIndex = value;} + + /// Returns an image index + int GetImageIndex() {return m_ImageIndex;} + + /// Return true if the page is enabled + bool GetEnabled() { return m_bEnabled; } + + /// Set the page enable/disable flag + /** + \param enabled - new page enable status + */ + void Enable(bool enabled) { m_bEnabled = enabled; } + + /// Set the page region + /** + \param n - number of points + \param points - array of points that construct the region + */ + void SetRegion(const size_t n, const wxPoint points[]) { m_region = wxRegion(n, points); } + + /// Get the page region + wxRegion& GetRegion() { return m_region ; } + + /// Set the 'x' button rectangle area + /** + \param xrect - the 'x' button rectangle + */ + void SetXRect(const wxRect& xrect) { m_xRect = xrect; } + + /// Get the 'x' button rectangle + wxRect& GetXRect() { return m_xRect; } +}; + +/// Button status +enum +{ + wxFNB_BTN_PRESSED, + wxFNB_BTN_HOVER, + wxFNB_BTN_NONE +}; + +/// Hit Test results +enum +{ + wxFNB_TAB, /// On a tab + wxFNB_X, /// On the X button + wxFNB_TAB_X, /// On the 'X' button (tab's X button) + wxFNB_LEFT_ARROW, /// On the rotate left arrow button + wxFNB_RIGHT_ARROW, /// On the rotate right arrow button + wxFNB_NOWHERE /// Anywhere else +}; + +/** +* \brief Notebook page +*/ +class wxPageContainerBase : public wxPanel +{ +protected: + + friend class wxFlatNotebookBase; + wxFlatNotebookImageList * m_ImageList; + +public: + /// Parametrized constructor + /** + \param parent - parent window + \param id - window ID + \param pos - window position + \param size - window size + \param style - window style + */ + wxPageContainerBase(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0); + /// Destructor + virtual ~wxPageContainerBase(void); + + /// Sets an image list associated with notebook pages + /** + \param imglist - image list object. + Image list assigned with this method will not be deleted by wxFlatNotebookBase's destructor, you must delete it yourself. + */ + virtual void SetImageList(wxFlatNotebookImageList * imglist) {m_ImageList = imglist;} + + /// Returns an image list object associated with wxFlatNotebookBase + virtual wxFlatNotebookImageList * GetImageList() {return m_ImageList;} + + /// Apends new notebook page + /** + \param caption - tab caption + \param selected - determines if new page should be selected automatically + \param imgindex - page image index + */ + virtual void AddPage(const wxString& caption, const bool selected = false, const int imgindex = -1); + + /// Inserts new notebook page + /** + \param index - page index + \param page - window to be appended + \param text - tab caption + \param select - determines if new page should be selected automatically + \param imgindex - page image index + */ + virtual bool InsertPage(size_t index, wxWindow* page, const wxString& text, bool select = false, const int imgindex = -1); + + /// Changes the selection from currently visible/selected page to the page given by index. + /** + \param page - index of page to be selected + */ + virtual void SetSelection(size_t page); + + /// Returns the current selection page index + virtual int GetSelection() { return m_iActivePage; } + + /// Advances the selection + /** + \param bForward - if set to true then selection should be advanced forward otherwise - backward + */ + virtual void AdvanceSelection(bool bForward); + + /// Return the number of pages + virtual size_t GetPageCount() { return m_pagesInfoVec.size(); } + + /// Returns the page caption + /** + \param page - page index + */ + virtual wxString GetPageText(size_t page) { return m_pagesInfoVec[page].GetCaption(); } + + /// Set the caption of the page + /** + \param page - page index + \param text - new page caption + */ + virtual bool SetPageText(size_t page, const wxString& text) { m_pagesInfoVec[page].SetCaption(text); return true; } + + /// Sets an image index of specified page + /** + \param page - page index + \param imgindex - new image index + */ + virtual void SetPageImageIndex(size_t page, int imgindex); + /// Returns an image index of specified page + /** + \param page - page index + */ + virtual int GetPageImageIndex(size_t page); + + /// Enable / Disable page + /** + \param page - page to enable/diable + \param enabled - set to true to enable the tab, false otherwise + */ + virtual void Enable(size_t page, bool enabled); + + /// Return Returns true if if the page is enabled + /** + \param page - page index + */ + virtual bool GetEnabled(size_t page); + + DECLARE_EVENT_TABLE() + // Event handlers + virtual void OnPaint(wxPaintEvent& event); + virtual void OnSize(wxSizeEvent& WXUNUSED(event)); + virtual void OnMouseMove(wxMouseEvent& event); + virtual void OnLeftDown(wxMouseEvent& event); + virtual void OnLeftUp(wxMouseEvent& event); + virtual void OnRightDown(wxMouseEvent& event); + virtual void OnMiddleDown(wxMouseEvent& event); + virtual void OnEraseBackground(wxEraseEvent& WXUNUSED(event)) { } + virtual void OnMouseLeave(wxMouseEvent& event); + virtual void OnMouseEnterWindow(wxMouseEvent& event); + +protected: + /// Check whether the style is set to default + virtual bool IsDefaultTabs(); + + /// Some styles does not allow drawing X on the active tab + /// If you dont want to allow it, override this function + virtual bool CanDrawXOnTab() { return true; } + + /// Return the button area space + virtual int GetButtonAreaWidth(void); + + /// File a tab with gradient color + virtual void FillGradientColor(wxBufferedDC& dc, const wxRect& rect); + + /// Return true if page is visible + virtual bool IsTabVisible(size_t page); + + /// Return if pt is anywhere on a tab, button or anywhere else + virtual int HitTest(const wxPoint& pt, wxPageInfo& pageInfo, int &tabIdx); + + /// Display tool tip when mouse is hovering a tab + virtual void ShowTabTooltip(int tabIdx); + + /// A wrapper from calling the DoDeletePage() + virtual void DeletePage(size_t page); + + /// Remove all pages from the container (it also deletes them) + virtual void DeleteAllPages(); + + /// Perform the actual deletion of a tab from the container + /// The window is also deleted using this function + virtual void DoDeletePage(size_t page); + + /// Preform the actual page selection + virtual void DoSetSelection(size_t page); + + /// Draw right arrow button to the right area of the tabs + virtual void DrawRightArrow(wxDC &dc); + + /// Draw left arrow button to the right area of the tabs + virtual void DrawLeftArrow (wxDC &dc); + + /// Draw 'x' button to the right area of the tabs + virtual void DrawX (wxDC &dc); + + /// Draw 'x' button on a tab at position rect.x rect.y + virtual void DrawTabX(wxDC &dc, const wxRect &rect, const int& tabIdx); + + /// Return the index of the last visible index + virtual int GetLastVisibleTab(); + + /// Return the number of tabs that can be scrolled left + /// starting from the first visible tab (i.e. m_nFrom) + virtual int GetNumTabsCanScrollLeft(); + + /// Return the number of visible tabs + virtual int GetNumOfVisibleTabs(); + + /** + * \brief Drop event handler, to be passed as function pointer to CTextDropTarget class. + * \param x X coordinate where the drop take place + * \param y Y coordinate where the drop take place + * \param nTabPage page index + * \param wnd_oldContainer pointer to wxPageContainerBase object that contained dragged page + * \return Drag operation identifier + */ + virtual wxDragResult OnDropTarget(wxCoord x, wxCoord y, int nTabPage, wxWindow * wnd_oldContainer); + + /** + * \brief Moves the tab page from one location to another + * \param nMove The index of the tab page to be moved. + * \param nMoveTo The index for the tab page, where it has to be moved + */ + virtual void MoveTabPage(int nMove, int nMoveTo); + + /// Check whether page can fit to the current + /// screen or a scrolling is required + /** + \param page - page index + */ + virtual bool CanFitToScreen(size_t page); + + /// Draw a bottom line for the tabs area + virtual void DrawTabsLine(wxDC& dc, const wxRect& rect); + + // Functions + void DrawVC71Tab(wxBufferedPaintDC& dc, const int& posx, const int &tabIdx, const bool& hasImage, const int &tabWidth, const int &tabHeight); + void DrawFancyTab(wxBufferedPaintDC& dc, const int& posx, const int &tabIdx, const bool& hasImage, const int &tabWidth, const int &tabHeight); + void DrawStandardTab(wxBufferedPaintDC& dc, const int& posx, const int &tabIdx, const bool& hasImage, const int &tabWidth, const int &tabHeight); + + // Navigation buttons position + int GetLeftButtonPos(); + int GetRightButtonPos(); + int GetXPos(); + int GetButtonsAreaLength(); + +protected: + + std::vector m_pagesInfoVec; + int m_iActivePage; + int m_nFrom; + + /// Drop target for enabling drag'n'drop of tabs + wxFNBDropTarget *m_pDropTarget; + + /// Pointer to the parent window + wxWindow *m_pParent; + + /// The right click menu + wxMenu* m_pRightClickMenu; + + /// Gradient colors + wxColour m_colorFrom, m_colorTo, m_colorBorder, m_activeTextColor, m_nonActiveTextColor, m_tabAreaColor, m_activeTabColor; + + /// X,>,< buttons status, can be one of + /// - Pressed + /// - Hover + /// - None + int m_nXButtonStatus, m_nLeftButtonStatus, m_nRightButtonStatus, m_nTabXButtonStatus; + + /// holds the button id in case a left click is done on one of them + int m_nLeftClickZone; +}; + +/** +* \brief Holds information about events associated with wxFlatNotebookBase objects +*/ +class wxFlatNotebookEvent : public wxNotifyEvent +{ + DECLARE_DYNAMIC_CLASS(wxFlatNotebookEvent) + size_t sel, oldsel; + +public: + /// Constructor + /** + \param commandType - event type + \param winid - window ID + \param nSel - current selection + \param nOldSel - old selection + */ + wxFlatNotebookEvent(wxEventType commandType = wxEVT_NULL, int winid = 0, int nSel = -1, int nOldSel = -1) + : wxNotifyEvent(commandType, winid), sel(nSel), oldsel(nOldSel) + {} + /// Sets the value of current selection + /** + \param s - index of currently selected page + */ + void SetSelection(int s) { sel = s; } + /// Sets the value of previous selection + /** + \param s - index of previously selected page + */ + void SetOldSelection(int s) { oldsel = s; } + /// Returns the index of currently selected page + int GetSelection() { return (int)sel; } + /// Returns the index of previously selected page + int GetOldSelection() { return (int)oldsel; } +}; + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Default implementation of the wxFlatNotebook +// +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +class wxFlatNotebook : public wxFlatNotebookBase +{ +public: + /** + * + * \param parent parent window + * \param id window ID + * \param pos window position + * \param size window size + * \param style window style + * \param name window class name + * \return + */ + wxFlatNotebook(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxT("FlatNotebook")) : + wxFlatNotebookBase(parent, id, pos, size, style, name) + { + m_pages = CreatePageContainer(); + Init(); + } + + /// Destructor + ~wxFlatNotebook(void) + {} +}; + +#define wxFN_IMPEXP + +BEGIN_DECLARE_EVENT_TYPES() + DECLARE_EXPORTED_EVENT_TYPE(wxFN_IMPEXP, wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CHANGED, 50000) + DECLARE_EXPORTED_EVENT_TYPE(wxFN_IMPEXP, wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CHANGING, 50001) + DECLARE_EXPORTED_EVENT_TYPE(wxFN_IMPEXP, wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CLOSING, 50002) + DECLARE_EXPORTED_EVENT_TYPE(wxFN_IMPEXP, wxEVT_COMMAND_FLATNOTEBOOK_CONTEXT_MENU, 50003) + DECLARE_EXPORTED_EVENT_TYPE(wxFN_IMPEXP, wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CLOSED, 50004) +END_DECLARE_EVENT_TYPES() + +typedef void (wxEvtHandler::*wxFlatNotebookEventFunction)(wxFlatNotebookEvent&); + +#define wxFlatNotebookEventHandler(func) \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxFlatNotebookEventFunction, &func) + +#define EVT_FLATNOTEBOOK_PAGE_CHANGED(winid, fn) \ + wx__DECLARE_EVT1(wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CHANGED, winid, wxFlatNotebookEventHandler(fn)) + +#define EVT_FLATNOTEBOOK_PAGE_CHANGING(winid, fn) \ + wx__DECLARE_EVT1(wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CHANGING, winid, wxFlatNotebookEventHandler(fn)) + +#define EVT_FLATNOTEBOOK_PAGE_CLOSING(winid, fn) \ + wx__DECLARE_EVT1(wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CLOSING, winid, wxFlatNotebookEventHandler(fn)) + +#define EVT_FLATNOTEBOOK_CONTEXT_MENU(winid, fn) \ + wx__DECLARE_EVT1(wxEVT_COMMAND_FLATNOTEBOOK_CONTEXT_MENU, winid, wxFlatNotebookEventHandler(fn)) + +#define EVT_FLATNOTEBOOK_PAGE_CLOSED(winid, fn) \ + wx__DECLARE_EVT1(wxEVT_COMMAND_FLATNOTEBOOK_PAGE_CLOSED, winid, wxFlatNotebookEventHandler(fn)) + + + +/////////////////////////////////////////////////////////////////////////////// +// +// XPM Images required by this control +// +/////////////////////////////////////////////////////////////////////////////// + +namespace FNB +{ + //////////////////////////////////////////////////////////// + // Images used by the control + //////////////////////////////////////////////////////////// + /* XPM */ + static char *left_arrow_disabled_xpm[] = { + /* width height num_colors chars_per_pixel */ + " 16 16 8 1", + /* colors */ + "` c #008080", + ". c #555555", + "# c #000000", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + /* pixels */ + "````````````````", + "````````````````", + "````````````````", + "````````.```````", + "```````..```````", + "``````.`.```````", + "`````.``.```````", + "````.```.```````", + "`````.``.```````", + "``````.`.```````", + "```````..```````", + "````````.```````", + "````````````````", + "````````````````", + "````````````````", + "````````````````" + }; + + /* XPM */ + static char *x_button_pressed_xpm[] = { + /* width height num_colors chars_per_pixel */ + " 16 16 8 1", + /* colors */ + "` c #008080", + ". c #4766e0", + "# c #9e9ede", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + /* pixels */ + "````````````````", + "`..............`", + "`.############.`", + "`.############.`", + "`.############.`", + "`.###aa####aa#.`", + "`.####aa##aa##.`", + "`.#####aaaa###.`", + "`.######aa####.`", + "`.#####aaaa###.`", + "`.####aa##aa##.`", + "`.###aa####aa#.`", + "`.############.`", + "`..............`", + "````````````````", + "````````````````" + }; + + + /* XPM */ + static char *left_arrow_xpm[] = { + /* width height num_colors chars_per_pixel */ + " 16 16 8 1", + /* colors */ + "` c #008080", + ". c #555555", + "# c #000000", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + /* pixels */ + "````````````````", + "````````````````", + "````````````````", + "````````.```````", + "```````..```````", + "``````...```````", + "`````....```````", + "````.....```````", + "`````....```````", + "``````...```````", + "```````..```````", + "````````.```````", + "````````````````", + "````````````````", + "````````````````", + "````````````````" + }; + + /* XPM */ + static char *x_button_hilite_xpm[] = { + /* width height num_colors chars_per_pixel */ + " 16 16 8 1", + /* colors */ + "` c #008080", + ". c #4766e0", + "# c #c9dafb", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + /* pixels */ + "````````````````", + "`..............`", + "`.############.`", + "`.############.`", + "`.##aa####aa##.`", + "`.###aa##aa###.`", + "`.####aaaa####.`", + "`.#####aa#####.`", + "`.####aaaa####.`", + "`.###aa##aa###.`", + "`.##aa####aa##.`", + "`.############.`", + "`.############.`", + "`..............`", + "````````````````", + "````````````````" + }; + + /* XPM */ + static char *x_button_xpm[] = { + /* width height num_colors chars_per_pixel */ + " 16 16 8 1", + /* colors */ + "` c #008080", + ". c #555555", + "# c #000000", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + /* pixels */ + "````````````````", + "````````````````", + "````````````````", + "````````````````", + "````..````..````", + "`````..``..`````", + "``````....``````", + "```````..```````", + "``````....``````", + "`````..``..`````", + "````..````..````", + "````````````````", + "````````````````", + "````````````````", + "````````````````", + "````````````````" + }; + + /* XPM */ + static char *left_arrow_pressed_xpm[] = { + /* width height num_colors chars_per_pixel */ + " 16 16 8 1", + /* colors */ + "` c #008080", + ". c #4766e0", + "# c #9e9ede", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + /* pixels */ + "````````````````", + "`..............`", + "`.############.`", + "`.############.`", + "`.#######a####.`", + "`.######aa####.`", + "`.#####aaa####.`", + "`.####aaaa####.`", + "`.###aaaaa####.`", + "`.####aaaa####.`", + "`.#####aaa####.`", + "`.######aa####.`", + "`.#######a####.`", + "`..............`", + "````````````````", + "````````````````" + }; + + /* XPM */ + static char *left_arrow_hilite_xpm[] = { + /* width height num_colors chars_per_pixel */ + " 16 16 8 1", + /* colors */ + "` c #008080", + ". c #4766e0", + "# c #c9dafb", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + /* pixels */ + "````````````````", + "`..............`", + "`.############.`", + "`.######a#####.`", + "`.#####aa#####.`", + "`.####aaa#####.`", + "`.###aaaa#####.`", + "`.##aaaaa#####.`", + "`.###aaaa#####.`", + "`.####aaa#####.`", + "`.#####aa#####.`", + "`.######a#####.`", + "`.############.`", + "`..............`", + "````````````````", + "````````````````" + }; + + /* XPM */ + static char *right_arrow_disabled_xpm[] = { + /* width height num_colors chars_per_pixel */ + " 16 16 8 1", + /* colors */ + "` c #008080", + ". c #555555", + "# c #000000", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + /* pixels */ + "````````````````", + "````````````````", + "````````````````", + "```````.````````", + "```````..```````", + "```````.`.``````", + "```````.``.`````", + "```````.```.````", + "```````.``.`````", + "```````.`.``````", + "```````..```````", + "```````.````````", + "````````````````", + "````````````````", + "````````````````", + "````````````````" + }; + + /* XPM */ + static char *right_arrow_hilite_xpm[] = { + /* width height num_colors chars_per_pixel */ + " 16 16 8 1", + /* colors */ + "` c #008080", + ". c #4766e0", + "# c #c9dafb", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + /* pixels */ + "````````````````", + "`..............`", + "`.############.`", + "`.####a#######.`", + "`.####aa######.`", + "`.####aaa#####.`", + "`.####aaaa####.`", + "`.####aaaaa###.`", + "`.####aaaa####.`", + "`.####aaa#####.`", + "`.####aa######.`", + "`.####a#######.`", + "`.############.`", + "`..............`", + "````````````````", + "````````````````" + }; + + /* XPM */ + static char *right_arrow_pressed_xpm[] = { + /* width height num_colors chars_per_pixel */ + " 16 16 8 1", + /* colors */ + "` c #008080", + ". c #4766e0", + "# c #9e9ede", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + /* pixels */ + "````````````````", + "`..............`", + "`.############.`", + "`.############.`", + "`.#####a######.`", + "`.#####aa#####.`", + "`.#####aaa####.`", + "`.#####aaaa###.`", + "`.#####aaaaa##.`", + "`.#####aaaa###.`", + "`.#####aaa####.`", + "`.#####aa#####.`", + "`.#####a######.`", + "`..............`", + "````````````````", + "````````````````" + }; + + + /* XPM */ + static char *right_arrow_xpm[] = { + /* width height num_colors chars_per_pixel */ + " 16 16 8 1", + /* colors */ + "` c #008080", + ". c #555555", + "# c #000000", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + /* pixels */ + "````````````````", + "````````````````", + "````````````````", + "```````.````````", + "```````..```````", + "```````...``````", + "```````....`````", + "```````.....````", + "```````....`````", + "```````...``````", + "```````..```````", + "```````.````````", + "````````````````", + "````````````````", + "````````````````", + "````````````````" + }; + + const int tab_x_size = 9; + + /* XPM */ + static char *tab_x_button_pressed_xpm[] = { + /* width height num_colors chars_per_pixel */ + " 9 9 8 1", + /* colors */ + "` c #4766e0", + ". c #9e9ede", + "# c #555555", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + /* pixels */ + "`````````", + "`.......`", + "`.......`", + "`..#...#`", + "`...#.#.`", + "`....#..`", + "`...#.#.`", + "`..#...#`", + "`````````" + }; + + /* XPM */ + static char *tab_x_button_xpm[] = { + /* width height num_colors chars_per_pixel */ + " 9 9 8 1", + /* colors */ + "` c #555555", + ". c #FFFFFF", + "# c #000000", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + /* pixels */ + "`````````", + "`.......`", + "`.`...`.`", + "`..`.`..`", + "`...`...`", + "`..`.`..`", + "`.`...`.`", + "`.......`", + "`````````" + }; + + /* XPM */ + static char *tab_x_button_hilite_xpm[] = { + /* width height num_colors chars_per_pixel */ + " 9 9 8 1", + /* colors */ + "` c #4766e0", + ". c #c9dafb", + "# c #000000", + "a c #000000", + "b c #000000", + "c c #000000", + "d c #000000", + "e c #000000", + /* pixels */ + "`````````", + "`.......`", + "`.#...#.`", + "`..#.#..`", + "`...#...`", + "`..#.#..`", + "`.#...#.`", + "`.......`", + "`````````" + }; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// +// End of XPM Images +// +////////////////////////////////////////////////////////////////////////////////////////////////// + +#endif // WXFLATNOTEBOOK_H