summaryrefslogtreecommitdiff
path: root/alf/alfnotebook.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'alf/alfnotebook.cpp')
-rw-r--r--alf/alfnotebook.cpp304
1 files changed, 304 insertions, 0 deletions
diff --git a/alf/alfnotebook.cpp b/alf/alfnotebook.cpp
new file mode 100644
index 0000000..82b2201
--- /dev/null
+++ b/alf/alfnotebook.cpp
@@ -0,0 +1,304 @@
+#include "alfpriv.h"
+#include "alfcompat.h"
+
+#define ALF_NB_ADDTAB (ALF_WM__BASE + 200)
+#define ALF_NB_TABCOUNT (ALF_WM__BASE + 201)
+#define ALF_NB_GETPANEL (ALF_WM__BASE + 202)
+#define ALF_NB_GETSELINDEX (ALF_WM__BASE + 203)
+#define ALF_NB_GETPNLINDEX (ALF_WM__BASE + 204)
+
+TCHAR *_alf_notebookClass = NULL;
+
+static int
+ALF_Notebook_InternalTabCount(HWND notebook, HWND tabControl)
+{
+ (void)notebook;
+ return TabCtrl_GetItemCount(tabControl);
+}
+
+static HWND
+ALF_Notebook_InternalTabPanel(HWND notebook, HWND tabControl, int index)
+{
+ (void)notebook;
+
+ TCITEM tci;
+ ZeroMemory(&tci, sizeof(tci));
+
+ tci.mask = TCIF_PARAM;
+
+ if (TabCtrl_GetItem(tabControl, index, &tci)) {
+ return (HWND)tci.lParam;
+ } else {
+ return NULL;
+ }
+}
+
+static int
+ALF_Notebook_InternalSelectedIndex(HWND notebook, HWND tabControl)
+{
+ (void)notebook;
+
+ return TabCtrl_GetCurSel(tabControl);
+}
+
+
+static void
+ALF_Notebook_InternalHandleTabChange(HWND hwndNotebook, HWND hwndTabCtrl)
+{
+ int selectedIndex = ALF_Notebook_InternalSelectedIndex(hwndNotebook, hwndTabCtrl);
+ int n = ALF_Notebook_InternalTabCount(hwndNotebook, hwndTabCtrl);
+
+ for (int i = 0; i < n; ++i) {
+ if (i == selectedIndex) {
+ ShowWindow(ALF_Notebook_InternalTabPanel(hwndNotebook, hwndTabCtrl, i), SW_SHOW);
+ } else {
+ ShowWindow(ALF_Notebook_InternalTabPanel(hwndNotebook, hwndTabCtrl, i), SW_HIDE);
+ }
+ }
+}
+
+
+static HWND
+ALF_Notebook_InternalAddTab(HWND notebook, HWND tabControl, const TCHAR *title)
+{
+ RECT r;
+ GetClientRect(tabControl, &r);
+ TabCtrl_AdjustRect(tabControl, FALSE, &r);
+ MapWindowRect(tabControl, notebook, &r);
+
+ HWND hwndPanel = ALF_CreatePanelWindow(notebook, (WORD)-1);
+ SetWindowPos(hwndPanel, NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOOWNERZORDER);
+
+ TCITEM tie;
+ ZeroMemory(&tie, sizeof(tie));
+
+ tie.mask = TCIF_TEXT | TCIF_PARAM;
+ tie.pszText = (TCHAR*)title;
+ tie.lParam = (LPARAM)hwndPanel;
+
+ TabCtrl_InsertItem(tabControl, ALF_Notebook_InternalTabCount(notebook, tabControl), &tie);
+ ALF_Notebook_InternalHandleTabChange(notebook, tabControl);
+
+ return hwndPanel;
+}
+
+
+static LRESULT CALLBACK
+ALF_Notebook_TabCtrlSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
+{
+ (void)uIdSubclass;
+ (void)dwRefData;
+
+ if (uMsg == WM_ERASEBKGND) {
+ // see: http://www.virtualdub.org/blog/pivot/entry.php?id=291
+ HDC hdc = (HDC)wParam;
+
+ RECT r;
+ GetClientRect(hwnd, &r);
+ TabCtrl_AdjustRect(hwnd, FALSE, &r);
+
+ ExcludeClipRect(hdc, r.left, r.top, r.right, r.bottom);
+ }
+ if (uMsg == 0x2000 + WM_NOTIFY) {
+ NMHDR *pnmh = (NMHDR*)lParam;
+ if (pnmh->code == TCN_SELCHANGE) {
+ ALF_Notebook_InternalHandleTabChange(GetParent(hwnd), hwnd);
+
+ return TRUE;
+ }
+ }
+ if (uMsg == WM_DESTROY) {
+ ALF_Compat_RemoveWindowSubclass(hwnd, ALF_Notebook_TabCtrlSubclassProc, 0);
+ }
+
+ return ALF_Compat_DefSubclassProc(hwnd, uMsg, wParam, lParam);
+}
+
+static LRESULT CALLBACK
+ALF__NotebookWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ if (ALF_ShouldMessageBubble(hwnd, uMsg, wParam, lParam))
+ return SendMessage(GetParent(hwnd), uMsg, wParam, lParam);
+
+ HWND hwndTabCtrl = (HWND)GetWindowLongPtr(hwnd, 0);
+
+ if (uMsg == WM_CREATE) {
+ hwndTabCtrl = CreateWindowEx(0,
+ WC_TABCONTROL,
+ TEXT(""),
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS,
+ 0, 0, 100, 100,
+ hwnd,
+ NULL,
+ ALF_HINSTANCE,
+ NULL);
+
+ ALF_Compat_SetWindowSubclass(hwndTabCtrl, ALF_Notebook_TabCtrlSubclassProc, 0, 0);
+
+ SetWindowLongPtr(hwnd, 0, (LONG_PTR)hwndTabCtrl);
+ } else if (uMsg == ALF_WM_APPLYFONTS) {
+ int n = ALF_Notebook_InternalTabCount(hwnd, hwndTabCtrl);
+ for (int i = 0; i < n; ++i) {
+ HWND p = ALF_Notebook_InternalTabPanel(hwnd, hwndTabCtrl, i);
+ SendMessage(p, ALF_WM_APPLYFONTS, wParam, lParam);
+ }
+
+ return TRUE;
+ } else if (uMsg == WM_SETFONT) {
+ SendMessage(hwndTabCtrl, WM_SETFONT, wParam, lParam);
+ } else if (uMsg == ALF_WM_QUERYSIZE) {
+ int n = ALF_Notebook_InternalTabCount(hwnd, hwndTabCtrl);
+ RECT r = { 0, 0, 0, 0 };
+ for (int i = 0; i < n; ++i) {
+ HWND p = ALF_Notebook_InternalTabPanel(hwnd, hwndTabCtrl, i);
+ SIZE s = { 0, 0 };
+ SendMessage(p, ALF_WM_QUERYSIZE, 0, (LPARAM)&s);
+ if (s.cx > r.right)
+ r.right = s.cx;
+ if (s.cy > r.bottom)
+ r.bottom = s.cy;
+ }
+
+ if (!r.right)
+ r.right = 100; // FIXME!
+ if (!r.bottom)
+ r.bottom = 100; // FIXME!
+
+ TabCtrl_AdjustRect(hwndTabCtrl, TRUE, &r);
+
+ SIZE *ps = (SIZE*)lParam;
+ if (!ps->cx) {
+ ps->cx = r.right - r.left;
+ }
+
+ if (!ps->cy) {
+ ps->cy = r.bottom - r.top;
+ }
+
+ return 0;
+ } else if (uMsg == WM_WINDOWPOSCHANGED) {
+ WINDOWPOS *pos = (WINDOWPOS *)lParam;
+ if (!(pos->flags & SWP_NOSIZE)) {
+ RECT r;
+ GetClientRect(hwnd, &r);
+ MoveWindow(hwndTabCtrl, 0, 0, r.right - r.left, r.bottom - r.top, FALSE);
+
+ GetClientRect(hwndTabCtrl, &r);
+ TabCtrl_AdjustRect(hwndTabCtrl, FALSE, &r);
+ MapWindowRect(hwndTabCtrl, hwnd, &r);
+
+ int n = ALF_Notebook_InternalTabCount(hwnd, hwndTabCtrl);
+ for (int i = 0; i < n; ++i) {
+ HWND p = ALF_Notebook_InternalTabPanel(hwnd, hwndTabCtrl, i);
+
+ MoveWindow(p, r.left, r.top, r.right - r.left, r.bottom - r.top, FALSE);
+ }
+
+ InvalidateRect(hwnd, NULL, TRUE);
+ }
+ } else if (uMsg == ALF_NB_ADDTAB) {
+ return (LRESULT)ALF_Notebook_InternalAddTab(hwnd, hwndTabCtrl, (TCHAR *)lParam);
+ } else if (uMsg == ALF_NB_TABCOUNT) {
+ return (LRESULT)ALF_Notebook_InternalTabCount(hwnd, hwndTabCtrl);
+ } else if (uMsg == ALF_NB_GETPANEL) {
+ return (LRESULT)ALF_Notebook_InternalTabPanel(hwnd, hwndTabCtrl, (int)lParam);
+ } else if (uMsg == ALF_NB_GETSELINDEX) {
+ return (LRESULT)ALF_Notebook_InternalSelectedIndex(hwnd, hwndTabCtrl);
+ }
+
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+void
+ALF_RegisterNotebookClass(void)
+{
+ WNDCLASS cls;
+ ZeroMemory(&cls, sizeof(cls));
+
+ TCHAR classNameBuf[256];
+ ALF_BuildUniqueName(classNameBuf, TEXT("ALFNotebook."), (ULONG_PTR)&_alf_notebookClass);
+
+ cls.hInstance = ALF_HINSTANCE;
+ cls.hCursor = LoadCursor(NULL, (LPTSTR)IDC_ARROW);
+ if (LOBYTE(LOWORD(GetVersion())) >= 4) {
+ cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);
+ } else {
+ // NT 3.x has white dialog backgrounds
+ cls.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
+ }
+ cls.lpszClassName = classNameBuf;
+ cls.cbWndExtra = sizeof(HWND);
+ cls.lpfnWndProc = ALF__NotebookWindowProc;
+
+ ATOM classatom = RegisterClass(&cls);
+ if (!classatom)
+ MessageBox(NULL, TEXT("FATAL: Could not register notebook class"), NULL, MB_OK);
+
+ _alf_notebookClass = MAKEINTATOM(classatom);
+}
+
+// tab control
+HWND
+ALF_AddNotebook(HWND parent, WORD id, UINT x, UINT y)
+{
+ HWND hwndNtbk = CreateWindowEx(WS_EX_CONTROLPARENT,
+ _alf_notebookClass,
+ TEXT(""),
+ WS_CHILD | WS_VISIBLE,
+ 0, 0, 100, 100,
+ parent,
+ (HMENU)(int)id,
+ ALF_HINSTANCE,
+ NULL);
+
+ ALFWidgetLayoutParams p;
+ ZeroMemory(&p, sizeof(p));
+ p.hwnd = hwndNtbk;
+ p.x = x;
+ p.y = y;
+ p.width = 0;
+ p.height = 0;
+ p.flags = ALF_QUERYSIZE | ALF_MESSAGEFONT | ALF_SENDAPPLYFONTS;
+
+ ALF_AddWidgetEx(parent, &p);
+
+ return hwndNtbk;
+}
+
+HWND
+ALF_NotebookAddTab(HWND notebook, const TCHAR *title)
+{
+ return (HWND)SendMessage(notebook, ALF_NB_ADDTAB, 0, (LPARAM)title);
+}
+
+int
+ALF_NotebookTabCount(HWND notebook)
+{
+ return (int)SendMessage(notebook, ALF_NB_TABCOUNT, 0, 0);
+}
+
+int
+ALF_NotebookTabIndex(HWND notebook, HWND tabPanel);
+
+HWND
+ALF_NotebookTabPanel(HWND notebook, int index)
+{
+ return (HWND)SendMessage(notebook, ALF_NB_GETPANEL, 0, (WPARAM)index);
+}
+
+int
+ALF_NotebookSelectedIndex(HWND notebook)
+{
+ return (int)SendMessage(notebook, ALF_NB_GETSELINDEX, 0, 0);
+}
+
+HWND
+ALF_NotebookSelectedPanel(HWND notebook)
+{
+ int i = ALF_NotebookSelectedIndex(notebook);
+ if (i >= 0) {
+ return ALF_NotebookTabPanel(notebook, i);
+ } else {
+ return NULL;
+ }
+}