#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
#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();
}
else
{
- wxLogLastError(_T("GetClassInfoEx(SysTabCtl32)"));
+ wxLogLastError(wxT("GetClassInfoEx(SysTabCtl32)"));
}
}
// 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
else if ( style & wxBK_RIGHT )
tabStyle |= TCS_VERTICAL | TCS_RIGHT;
- // ex style
- if ( exstyle )
- {
- // note that we never want to have the default WS_EX_CLIENTEDGE style
- // as it looks too ugly for the notebooks
- *exstyle = 0;
- }
-
return tabStyle;
}
{
wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("notebook page out of range") );
+ const int selOld = m_nSelection;
+
if ( m_nSelection == wxNOT_FOUND || nPage != (size_t)m_nSelection )
{
TabCtrl_SetCurSel(GetHwnd(), nPage);
UpdateSelection(nPage);
}
- return m_nSelection;
+ return selOld;
}
bool wxNotebook::SetPageText(size_t nPage, const wxString& strText)
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;
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;
}
void wxNotebook::AdjustPageSize(wxNotebookPage *page)
{
- wxCHECK_RET( page, _T("NULL page in wxNotebook::AdjustPageSize") );
+ wxCHECK_RET( page, wxT("NULL page in wxNotebook::AdjustPageSize") );
const wxRect r = GetPageSize();
if ( !r.IsEmpty() )
bool bSelect,
int imageId)
{
- wxCHECK_MSG( pPage != NULL, false, _T("NULL page in wxNotebook::InsertPage") );
+ wxCHECK_MSG( pPage != NULL, false, wxT("NULL page in wxNotebook::InsertPage") );
wxCHECK_MSG( IS_VALID_PAGE(nPage) || nPage == GetPageCount(), false,
- _T("invalid index in wxNotebook::InsertPage") );
+ wxT("invalid index in wxNotebook::InsertPage") );
wxASSERT_MSG( pPage->GetParent() == this,
- _T("notebook pages must have notebook as parent") );
+ wxT("notebook pages must have notebook as parent") );
// add a new tab to the control
// ----------------------------
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
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 )
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);
}
}
}
}
}
-WXHBRUSH wxNotebook::MSWGetBgBrushForChild(WXHDC hDC, WXHWND hWnd)
+WXHBRUSH wxNotebook::MSWGetBgBrushForChild(WXHDC hDC, wxWindow *child)
{
if ( m_hbrBackground )
{
// before drawing with the background brush, we need to position it
// correctly
RECT rc;
- ::GetWindowRect((HWND)hWnd, &rc);
+ ::GetWindowRect(GetHwndOf(child), &rc);
::MapWindowPoints(NULL, GetHwnd(), (POINT *)&rc, 1);
if ( !::SetBrushOrgEx((HDC)hDC, -rc.left, -rc.top, NULL) )
{
- wxLogLastError(_T("SetBrushOrgEx(notebook bg brush)"));
+ wxLogLastError(wxT("SetBrushOrgEx(notebook bg brush)"));
}
return m_hbrBackground;
}
- return wxNotebookBase::MSWGetBgBrushForChild(hDC, hWnd);
+ return wxNotebookBase::MSWGetBgBrushForChild(hDC, child);
}
bool wxNotebook::MSWPrintChild(WXHDC hDC, wxWindow *child)
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;
}