#include "wx/sysopt.h"
#include "wx/msw/private.h"
+#include "wx/msw/dc.h"
#include <windowsx.h>
#include "wx/msw/winundef.h"
#endif // USE_NOTEBOOK_ANTIFLICKER
+// ----------------------------------------------------------------------------
+// global functions
+// ----------------------------------------------------------------------------
+
+static bool HasTroubleWithNonTopTabs()
+{
+ const int verComCtl32 = wxApp::GetComCtl32Version();
+
+ // 600 is XP, 616 is Vista -- and both have a problem with tabs not on top
+ // (but don't just test for >= 600 as Microsoft might decide to fix it in
+ // later versions, who knows...)
+ return verComCtl32 >= 600 && verComCtl32 <= 616;
+}
+
// ----------------------------------------------------------------------------
// event table
// ----------------------------------------------------------------------------
WX_DEFINE_LIST( wxNotebookPageInfoList )
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED)
-DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING)
-
-BEGIN_EVENT_TABLE(wxNotebook, wxControl)
+BEGIN_EVENT_TABLE(wxNotebook, wxBookCtrlBase)
EVT_NOTEBOOK_PAGE_CHANGED(wxID_ANY, wxNotebook::OnSelChange)
EVT_SIZE(wxNotebook::OnSize)
EVT_NAVIGATION_KEY(wxNotebook::OnNavigationKey)
wxEND_FLAGS( wxNotebookStyle )
-IMPLEMENT_DYNAMIC_CLASS_XTI(wxNotebook, wxControl,"wx/notebook.h")
+IMPLEMENT_DYNAMIC_CLASS_XTI(wxNotebook, wxBookCtrlBase,"wx/notebook.h")
IMPLEMENT_DYNAMIC_CLASS_XTI(wxNotebookPageInfo, wxObject , "wx/notebook.h" )
wxCOLLECTION_TYPE_INFO( wxNotebookPageInfo * , wxNotebookPageInfoList ) ;
}
wxBEGIN_PROPERTIES_TABLE(wxNotebook)
- wxEVENT_PROPERTY( PageChanging , wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING , wxNotebookEvent )
- wxEVENT_PROPERTY( PageChanged , wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED , wxNotebookEvent )
+ wxEVENT_PROPERTY( PageChanging , wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING , wxBookCtrlEvent )
+ wxEVENT_PROPERTY( PageChanged , wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED , wxBookCtrlEvent )
wxPROPERTY_COLLECTION( PageInfos , wxNotebookPageInfoList , wxNotebookPageInfo* , AddPageInfo , GetPageInfos , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
wxPROPERTY_FLAGS( WindowStyle , wxNotebookStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
wxCONSTRUCTOR_4( wxNotebookPageInfo , wxNotebookPage* , Page , wxString , Text , bool , Selected , int , ImageId )
#else
-IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxControl)
+IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxBookCtrlBase)
IMPLEMENT_DYNAMIC_CLASS(wxNotebookPageInfo, wxObject )
#endif
-IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxNotifyEvent)
// ============================================================================
// implementation
void wxNotebook::Init()
{
m_imageList = NULL;
- m_nSelection = -1;
+ m_nSelection = wxNOT_FOUND;
#if wxUSE_UXTHEME
m_hbrBackground = NULL;
#endif
#if !wxUSE_UXTHEME
- // ComCtl32 notebook tabs simply don't work unless they're on top if we have uxtheme, we can
- // work around it later (after control creation), but if we don't have uxtheme, we have to clear
- // those styles
- const int verComCtl32 = wxApp::GetComCtl32Version();
- if ( verComCtl32 == 600 )
+ // ComCtl32 notebook tabs simply don't work unless they're on top if we
+ // have uxtheme, we can work around it later (after control creation), but
+ // if we have been compiled without uxtheme support, we have to clear those
+ // styles
+ if ( HasTroubleWithNonTopTabs() )
{
style &= ~(wxBK_BOTTOM | wxBK_LEFT | wxBK_RIGHT);
}
#endif //wxUSE_UXTHEME
+#if defined(__WINE__) && wxUSE_UNICODE
+ LPCTSTR className = L"SysTabControl32";
+#else
LPCTSTR className = WC_TABCONTROL;
+#endif
#if USE_NOTEBOOK_ANTIFLICKER
// SysTabCtl32 class has natively CS_HREDRAW and CS_VREDRAW enabled and it
if ( ::GetClassInfo(NULL, WC_TABCONTROL, &wc) )
{
gs_wndprocNotebook =
- wx_reinterpret_cast(WXFARPROC, wc.lpfnWndProc);
+ reinterpret_cast<WXFARPROC>(wc.lpfnWndProc);
wc.lpszClassName = wxT("_wx_SysTabCtl32");
wc.style &= ~(CS_HREDRAW | CS_VREDRAW);
wc.hInstance = wxGetInstance();
// comctl32.dll 6.0 doesn't support non-top tabs with visual styles (the
// control is simply not rendered correctly), so we disable themes
// if possible, otherwise we simply clear the styles.
- // It's probably not possible to have UXTHEME without ComCtl32 6 or better, but lets
- // check it anyway.
- const int verComCtl32 = wxApp::GetComCtl32Version();
- if ( verComCtl32 == 600 )
+ if ( HasTroubleWithNonTopTabs() &&
+ (style & (wxBK_BOTTOM | wxBK_LEFT | wxBK_RIGHT)) )
{
// check if we use themes at all -- if we don't, we're still okay
- if ( wxUxThemeEngine::GetIfActive() && (style & (wxBK_BOTTOM|wxBK_LEFT|wxBK_RIGHT)))
+ if ( wxUxThemeEngine::GetIfActive() )
{
- wxUxThemeEngine::GetIfActive()->SetWindowTheme((HWND)this->GetHandle(), L"", L"");
- SetBackgroundColour(GetThemeBackgroundColour()); //correct the background color for the new non-themed control
+ wxUxThemeEngine::GetIfActive()->SetWindowTheme(GetHwnd(), L"", L"");
+
+ // correct the background color for the new non-themed control
+ SetBackgroundColour(GetThemeBackgroundColour());
}
}
#endif // wxUSE_UXTHEME
{
wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("notebook page out of range") );
- if ( int(nPage) != m_nSelection )
+ if ( m_nSelection == wxNOT_FOUND || nPage != (size_t)m_nSelection )
{
- wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, m_windowId);
- event.SetSelection(nPage);
- event.SetOldSelection(m_nSelection);
- event.SetEventObject(this);
- if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
+ if ( SendPageChangingEvent(nPage) )
{
// program allows the page change
- event.SetEventType(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED);
- (void)GetEventHandler()->ProcessEvent(event);
+ SendPageChangedEvent(m_nSelection, nPage);
- TabCtrl_SetCurSel(GetHwnd(), nPage);
+ TabCtrl_SetCurSel(GetHwnd(), nPage);
}
}
return m_nSelection;
}
-void wxNotebook::UpdateSelection(size_t newsel)
+void wxNotebook::UpdateSelection(int selNew)
{
- if ( m_nSelection != -1 )
+ if ( m_nSelection != wxNOT_FOUND )
m_pages[m_nSelection]->Show(false);
- if ( newsel != -1 )
+ if ( selNew != wxNOT_FOUND )
{
- wxNotebookPage *pPage = m_pages[newsel];
+ wxNotebookPage *pPage = m_pages[selNew];
pPage->Show(true);
}
if ( ::IsWindowVisible(GetHwnd()) )
SetFocus();
- m_nSelection = newsel;
+ m_nSelection = selNew;
}
int wxNotebook::ChangeSelection(size_t nPage)
{
wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("notebook page out of range") );
- if ( int(nPage) != m_nSelection )
+ if ( m_nSelection == wxNOT_FOUND || nPage != (size_t)m_nSelection )
{
TabCtrl_SetCurSel(GetHwnd(), nPage);
TC_ITEM tcItem;
tcItem.mask = TCIF_TEXT;
- tcItem.pszText = (wxChar *)strText.c_str();
+ tcItem.pszText = (wxChar *)strText.wx_str();
if ( !HasFlag(wxNB_MULTILINE) )
return TabCtrl_SetItem(GetHwnd(), nPage, &tcItem) != 0;
TC_ITEM tcItem;
tcItem.mask = TCIF_IMAGE;
- return TabCtrl_GetItem(GetHwnd(), nPage, &tcItem) ? tcItem.iImage : wxNOT_FOUND;
+ return TabCtrl_GetItem(GetHwnd(), nPage, &tcItem) ? tcItem.iImage
+ : wxNOT_FOUND;
}
bool wxNotebook::SetPageImage(size_t nPage, int nImage)
if ( imageList )
{
- (void) TabCtrl_SetImageList(GetHwnd(), (HIMAGELIST)imageList->GetHIMAGELIST());
+ (void) TabCtrl_SetImageList(GetHwnd(), GetHimagelistOf(imageList));
}
}
tabSize.y = rect.bottom - rect.top;
}
+ const int rows = GetRowCount();
+
// add an extra margin in both directions
const int MARGIN = 8;
if ( IsVertical() )
{
sizeTotal.x += MARGIN;
- sizeTotal.y += tabSize.y + MARGIN;
+ sizeTotal.y += tabSize.y * rows + MARGIN;
}
else // horizontal layout
{
- sizeTotal.x += tabSize.x + MARGIN;
+ sizeTotal.x += tabSize.x * rows + MARGIN;
sizeTotal.y += MARGIN;
}
if ( m_pages.IsEmpty() )
{
// no selection any more, the notebook becamse empty
- m_nSelection = -1;
+ m_nSelection = wxNOT_FOUND;
}
else // notebook still not empty
{
int selNew = TabCtrl_GetCurSel(GetHwnd());
- if (selNew != -1)
+ if ( selNew != wxNOT_FOUND )
{
// No selection change, just refresh the current selection.
// Because it could be that the slection index changed
// m_nSelection must be always valid so reset it before calling
// SetSelection()
- m_nSelection = -1;
+ m_nSelection = wxNOT_FOUND;
SetSelection(selNew);
}
else
TabCtrl_DeleteAllItems(GetHwnd());
- m_nSelection = -1;
+ m_nSelection = wxNOT_FOUND;
InvalidateBestSize();
return true;
if ( !strText.empty() )
{
tcItem.mask |= TCIF_TEXT;
- tcItem.pszText = (wxChar *)strText.c_str(); // const_cast
+ tcItem.pszText = (wxChar *)strText.wx_str(); // const_cast
}
// hide the page: unless it is selected, it shouldn't be shown (and if it
// so the first panel gets the correct themed background
if ( m_pages.empty() )
{
+#if wxUSE_UXTHEME
UpdateBgBrush();
+#endif // wxUSE_UXTHEME
}
// succeeded: save the pointer to the page
// some page should be selected: either this one or the first one if there
// is still no selection
- int selNew = -1;
+ int selNew = wxNOT_FOUND;
if ( bSelect )
selNew = nPage;
- else if ( m_nSelection == -1 )
+ else if ( m_nSelection == wxNOT_FOUND )
selNew = 0;
- if ( selNew != -1 )
+ if ( selNew != wxNOT_FOUND )
SetSelection(selNew);
InvalidateBestSize();
wxBitmap bmp(rc.right, rc.bottom);
memdc.SelectObject(bmp);
+ const wxLayoutDirection dir = dc.GetLayoutDirection();
+ memdc.SetLayoutDirection(dir);
+
// if there is no special brush just use the solid background colour
#if wxUSE_UXTHEME
HBRUSH hbr = (HBRUSH)m_hbrBackground;
hbr = GetHbrushOf(brush);
}
- ::FillRect(GetHdcOf(memdc), &rc, hbr);
+ wxMSWDCImpl *impl = (wxMSWDCImpl*) memdc.GetImpl();
- MSWDefWindowProc(WM_PAINT, (WPARAM)memdc.GetHDC(), 0);
+ ::FillRect(GetHdcOf(*impl), &rc, hbr);
- dc.Blit(0, 0, rc.right, rc.bottom, &memdc, 0, 0);
+ MSWDefWindowProc(WM_PAINT, (WPARAM)(impl->GetHDC()), 0);
+
+ // For some reason in RTL mode, source offset has to be -1, otherwise the
+ // right border (physical) remains unpainted.
+ const wxCoord ofs = dir == wxLayout_RightToLeft ? -1 : 0;
+ dc.Blit(ofs, 0, rc.right, rc.bottom, &memdc, ofs, 0);
}
#endif // USE_NOTEBOOK_ANTIFLICKER
MAKELPARAM(rc.right, rc.bottom));
s_isInOnSize = false;
}
+
+ // The best size depends on the number of rows of tabs, which can
+ // change when the notepad is resized.
+ InvalidateBestSize();
}
#if wxUSE_UXTHEME
event.Skip();
}
-void wxNotebook::OnSelChange(wxNotebookEvent& event)
+void wxNotebook::OnSelChange(wxBookCtrlEvent& event)
{
// is it our tab control?
if ( event.GetEventObject() == this )
{
// no, it doesn't come from child, case (b) or (c): forward to a
// page but only if direction is backwards (TAB) or from ourselves,
- if ( m_nSelection != -1 &&
+ if ( m_nSelection != wxNOT_FOUND &&
(!event.GetDirection() || isFromSelf) )
{
// so that the page knows that the event comes from it's parent
event.SetEventObject(this);
wxWindow *page = m_pages[m_nSelection];
- if ( !page->GetEventHandler()->ProcessEvent(event) )
+ if ( !page->HandleWindowEvent(event) )
{
page->SetFocus();
}
else if ( parent )
{
event.SetCurrentFocus(this);
- parent->GetEventHandler()->ProcessEvent(event);
+ parent->HandleWindowEvent(event);
}
}
}
if (hTheme)
{
// This is total guesswork.
- // See PlatformSDK\Include\Tmschema.h for values
+ // See PlatformSDK\Include\Tmschema.h for values.
+ // JACS: can also use 9 (TABP_PANE)
COLORREF themeColor;
- wxUxThemeEngine::Get()->GetThemeColor(
+ bool success = (S_OK == wxUxThemeEngine::Get()->GetThemeColor(
hTheme,
10 /* TABP_BODY */,
1 /* NORMAL */,
3821 /* FILLCOLORHINT */,
- &themeColor);
+ &themeColor));
+ if (!success)
+ return GetBackgroundColour();
/*
[DS] Workaround for WindowBlinds:
&themeColor);
}
- return wxRGBToColour(themeColor);
+ wxColour colour = wxRGBToColour(themeColor);
+
+ // Under Vista, the tab background colour is reported incorrectly.
+ // So for the default theme at least, hard-code the colour to something
+ // that will blend in.
+
+ static int s_AeroStatus = -1;
+ if (s_AeroStatus == -1)
+ {
+ WCHAR szwThemeFile[1024];
+ WCHAR szwThemeColor[256];
+ if (S_OK == wxUxThemeEngine::Get()->GetCurrentThemeName(szwThemeFile, 1024, szwThemeColor, 256, NULL, 0))
+ {
+ wxString themeFile(szwThemeFile), themeColor(szwThemeColor);
+ if (themeFile.Find(wxT("Aero")) != -1 && themeColor == wxT("NormalColor"))
+ s_AeroStatus = 1;
+ else
+ s_AeroStatus = 0;
+ }
+ else
+ s_AeroStatus = 0;
+ }
+
+ if (s_AeroStatus == 1)
+ colour = wxColour(255, 255, 255);
+
+ return colour;
}
}
#endif // wxUSE_UXTHEME
bool wxNotebook::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM* result)
{
- wxNotebookEvent event(wxEVT_NULL, m_windowId);
+ wxBookCtrlEvent event(wxEVT_NULL, m_windowId);
NMHDR* hdr = (NMHDR *)lParam;
switch ( hdr->code ) {
event.SetEventObject(this);
event.SetInt(idCtrl);
- bool processed = GetEventHandler()->ProcessEvent(event);
+ bool processed = HandleWindowEvent(event);
*result = !event.IsAllowed();
return processed;
}