void
 resize()
 {
     // No point in doing this before we have the client size (ie at first construction):
     if (m_client[1] > 0) {
         uint        sd = 1;
         FgVect2I    pos(0),
                     sz = m_client;
         pos[sd] = -m_si.nPos;
         for (size_t ii=0; ii<m_panes.size(); ++ii) {
             sz[sd] = m_panes[ii]->getMinSize()[sd];
             if ((pos[sd] > m_client[sd]) || (pos[sd]+sz[sd] < 0))
                 m_panes[ii]->showWindow(false);
             else {
                 m_panes[ii]->moveWindow(pos,sz);
                 m_panes[ii]->showWindow(true);
             }
             pos[sd] += sz[sd];
         }
         // Note that Windows wants the total range of the scrollable area,
         // not the effective slider range resulting from subtracting the 
         // currently displayed range:
         m_si.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_POS | SIF_RANGE;
         m_si.nMax = sumDims()[sd];
         m_si.nPage = m_client[sd];
         // Windows will clamp the position and otherwise adjust:
         SetScrollInfo(hwndThis,SB_VERT,&m_si,TRUE);
         m_si.fMask = SIF_ALL;
         GetScrollInfo(hwndThis,SB_VERT,&m_si);
     }
 }
 virtual void
 saveState()
 {
     fgSaveXml(m_store+".xml",m_currPane,false);
     for (size_t ii=0; ii<m_panes.size(); ++ii)
         m_panes[ii]->saveState();
 }
 virtual FgVect2B
 wantStretch() const
 {
     for (size_t ii=0; ii<m_panes.size(); ++ii)
         if (m_panes[ii]->wantStretch()[0])
             return FgVect2B(true,true);
     return FgVect2B(false,true);
 }
 FgGuiWinTabs(const FgGuiApiTabs & api)
     : m_api(api)
 {
     FGASSERT(m_api.tabs.size()>0);
     for (size_t ii=0; ii<m_api.tabs.size(); ++ii)
         m_panes.push_back(api.tabs[ii].win->getInstance());
     m_currPane = 0;
 }
 FgVect2UI
 sumDims() const
 {
     FgVect2UI   sum(0);
     for (size_t ii=0; ii<m_panes.size(); ++ii)
         sum += m_panes[ii]->getMinSize();
     return sum;
 }
 virtual FgVect2UI
 getMinSize() const
 {
     FgVect2UI   max(0);
     for (size_t ii=0; ii<m_panes.size(); ++ii) {
         const FgGuiTab &    tab = m_api.tabs[ii];
         FgVect2UI           pad(tab.padLeft+tab.padRight,tab.padTop+tab.padBottom);
         max = fgMax(max,m_panes[ii]->getMinSize()+pad);
     }
     return max + FgVect2UI(0,37);
 }
    virtual void
    updateIfChanged()
    {
//fgout << fgnl << "SplitScroll::updateIfChanged";
        if (g_gg.dg.update(m_api.updateFlagIdx)) {
//fgout << " ... updating" << fgpush;
            // call DestroyWindow in all created sub-windows:
            for (size_t ii=0; ii<m_panes.size(); ++ii)
                m_panes[ii]->destroy();
            FgGuiPtrs            panes = m_api.getPanes();
            m_panes.resize(panes.size());
            for (size_t ii=0; ii<m_panes.size(); ++ii) {
                m_panes[ii] = panes[ii]->getInstance();
                m_panes[ii]->create(hwndThis,int(ii),m_store+"_"+fgToString(ii),0UL,true);
            }
//fgout << fgpop;
        }
        for (size_t ii=0; ii<m_panes.size(); ++ii)
            m_panes[ii]->updateIfChanged();
    }
    virtual void
    create(HWND parentHwnd,int ident,const FgString & store,DWORD extStyle,bool visible)
    {
//fgout << fgnl << "Tabs::create visible: " << visible << " extStyle: " << extStyle << fgpush;
        m_store = store;
        uint        cp;
        if (fgLoadXml(m_store+".xml",cp,false))
            if (cp < m_panes.size())
                m_currPane = cp;
        FgCreateChild   cc;
        cc.extStyle = extStyle;
        cc.visible = visible;
        fgCreateChild(parentHwnd,ident,this,cc);
//fgout << fgpop;
    }
    LRESULT
    wndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
    {
        if (msg == WM_CREATE) {
//fgout << fgnl << "Tabs::WM_CREATE" << fgpush;
            hwndThis = hwnd;
            // Creating the panes before the tabs fixes the problem of trackbars not being visible
            // on first paint (almost ... top/bottom arrows don't appear). No idea why.
            for (size_t ii=0; ii<m_panes.size(); ++ii) {
                // Set visibility here to avoid sending 'ShowWindow' messages, which also
                // send WM_SIZE. The sizing will all be done after creation when ShowWindow
                // is called from the client level.
                m_panes[ii]->create(hwnd,
                    int(ii+1),  // Child identifiers start at 1 since 0 taken above. Not used anyway.
                    m_store+"_"+fgToString(ii),
                    NULL,
                    ii==m_currPane);
            }
            m_tabHwnd = 
                CreateWindowEx(0,
                    WC_TABCONTROL,
                    L"",
                    WS_CHILD | WS_VISIBLE,
                    0,0,0,0,
                    hwnd,
                    0,      // Identifier 0
                    s_fgGuiWin.hinst,
                    NULL);
            TCITEM  tc = {0};
            tc.mask = TCIF_TEXT;
            for (size_t ii=0; ii<m_panes.size(); ++ii) {
                wstring     wstr = m_api.tabs[ii].label.as_wstring();
                wstr += wchar_t(0);
                tc.pszText = &wstr[0];
                TabCtrl_InsertItem(m_tabHwnd,ii,&tc);
            }
            SendMessage(m_tabHwnd,TCM_SETCURSEL,m_currPane,0);
            if (m_api.tabs[m_currPane].onSelect != NULL)
                m_api.tabs[m_currPane].onSelect();
//fgout << fgpop;
            return 0;
        }
        else if (msg == WM_SIZE) {
            m_client = FgVect2I(LOWORD(lParam),HIWORD(lParam));
            if (m_client[0] * m_client[1] > 0) {
//fgout << fgnl << "Tabs::WM_SIZE: " << m_api.tabs[0].label << " : " << m_client << fgpush;
                resize(hwnd);
//fgout << fgpop;
            }
            return 0;
        }
        else if (msg == WM_NOTIFY) {
            LPNMHDR lpnmhdr = (LPNMHDR)lParam;
            if (lpnmhdr->code == TCN_SELCHANGE) {
                int     idx = int(SendMessage(m_tabHwnd,TCM_GETCURSEL,0,0));
                // This can apparently be -1 for 'no tab selected':
                if ((idx >= 0) && (size_t(idx) < m_panes.size())) {
//fgout << fgnl << "Tabs::WM_NOTIFY: " << idx << fgpush;
                    if (uint(idx) != m_currPane) {
                        m_panes[m_currPane]->showWindow(false);
                        m_currPane = uint(idx);
                        // Must do update check and resize since these are not done when the
                        // tab is not visible:
                        m_panes[m_currPane]->updateIfChanged();
                        resizeCurrPane();
                        m_panes[m_currPane]->showWindow(true);
                        if (m_api.tabs[m_currPane].onSelect != NULL)
                            m_api.tabs[m_currPane].onSelect();
                        InvalidateRect(hwndThis,NULL,TRUE);
                    }
//fgout << fgpop;
                }
            }
            return 0;
        }
        else if (msg == WM_PAINT) {
//fgout << fgnl << "Tabs::WM_PAINT";
        }
        return DefWindowProc(hwnd,msg,wParam,lParam);
    }
    LRESULT
    wndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
    {
        if (message == WM_CREATE) {
//fgout << fgnl << "SplitScroll::WM_CREATE" << fgpush;
            hwndThis = hwnd;
            FGASSERT(m_panes.empty());
            FgGuiPtrs   panes = m_api.getPanes();
            m_panes.resize(panes.size());
            for (size_t ii=0; ii<m_panes.size(); ++ii) {
                m_panes[ii] = panes[ii]->getInstance();
                m_panes[ii]->create(hwndThis,int(ii),m_store+"_"+fgToString(ii),0UL,true);
            }
            g_gg.dg.update(m_api.updateFlagIdx);
//fgout << fgpop;
            return 0;
        }
        else if (message == WM_SIZE) {
            m_client = FgVect2I(LOWORD(lParam),HIWORD(lParam));
            if (m_client[0] * m_client[1] > 0) {
//fgout << fgnl << "SplitScroll::WM_SIZE: " << m_client << fgpush;
                resize();
//fgout << fgpop;
            }
            return 0;
        }
        else if (message == WM_VSCROLL) {
//fgout << "SplitScroll::WM_VSCROLL";
            int     tmp = m_si.nPos;
            // Get the current state, esp. trackbar drag position:
            m_si.fMask = SIF_ALL;
            GetScrollInfo(hwnd,SB_VERT,&m_si);
            int     msg = LOWORD(wParam);
            if (msg == SB_TOP)
                m_si.nPos = m_si.nMin;
            else if (msg == SB_BOTTOM)
                m_si.nPos = m_si.nMax;
            else if (msg == SB_LINEUP)
                m_si.nPos -= 5;
            else if (msg == SB_LINEDOWN)
                m_si.nPos += 5;
            else if (msg == SB_PAGEUP)
                m_si.nPos -= m_client[1];
            else if (msg == SB_PAGEDOWN)
                m_si.nPos += m_client[1];
            else if (msg == SB_THUMBTRACK)
                m_si.nPos = m_si.nTrackPos;
            m_si.fMask = SIF_POS;
            SetScrollInfo(hwnd,SB_VERT,&m_si,TRUE);
            // Windows may clamp the position:
            GetScrollInfo(hwnd,SB_VERT,&m_si);
            if (m_si.nPos != tmp) {
                resize();
                InvalidateRect(hwndThis,NULL,TRUE);
            }
            return 0;
        }
        else if (message == WM_PAINT) {
//fgout << fgnl << "SplitScroll::WM_PAINT";
        }
        return DefWindowProc(hwnd,message,wParam,lParam);
    }
 virtual void
 saveState()
 {
     for (size_t ii=0; ii<m_panes.size(); ++ii)
         m_panes[ii]->saveState();
 }
Esempio n. 12
0
    LRESULT
    wndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
    {
        switch (message)
        {
        case WM_CREATE:
            {
//fgout << fgnl << "FgGuiWinTabs::WM_CREATE " << m_api.tabs[0].label;
                hwndThis = hwnd;
                m_tabHwnd = 
                    CreateWindowEx(0,
                        WC_TABCONTROL,
                        L"",
                        WS_CHILD | WS_VISIBLE | TCS_FIXEDWIDTH,
                        0,0,0,0,
                        hwnd,
                        NULL,
                        s_fgGuiWin.hinst,
                        NULL);
                TCITEM  tc = {0};
                tc.mask = TCIF_TEXT;
                for (size_t ii=0; ii<m_panes.size(); ++ii) {
                    wstring     wstr = m_api.tabs[ii].label.as_wstring();
                    wstr += wchar_t(0);
                    tc.pszText = &wstr[0];
                    TabCtrl_InsertItem(m_tabHwnd,ii,&tc);
                    m_panes[ii]->create(hwnd,int(ii),m_store+"_"+fgToString(ii),NULL,false);
                }
                SendMessage(m_tabHwnd,TCM_SETCURSEL,m_currPane,0);
                m_panes[m_currPane]->showWindow(true);
                return 0;
            }
        case WM_SIZE:
            {
                m_client = FgVect2I(LOWORD(lParam),HIWORD(lParam));
//fgout << fgnl << "FgGuiWinTabs::WM_SIZE " << m_api.tabs[0].label << " : " << m_client;
                if (m_client[0] * m_client[1] > 0)
                    resize(hwnd);
                return 0;
            }
        case WM_NOTIFY:
            {
                LPNMHDR lpnmhdr = (LPNMHDR)lParam;
                if (lpnmhdr->code == TCN_SELCHANGE) {
                    int     idx = int(SendMessage(m_tabHwnd,TCM_GETCURSEL,0,0));
                    // This can apparently be -1 for 'no tab selected':
                    if ((idx >= 0) && (size_t(idx) < m_panes.size())) {
                        if (uint(idx) != m_currPane) {
                            m_panes[m_currPane]->showWindow(false);
                            m_currPane = uint(idx);
                            m_panes[m_currPane]->showWindow(true);
                            resizeCurrPane();
                            m_panes[m_currPane]->updateIfChanged();
                            // This is needed only for the first time a tab is selected, and only
                            // for *some* of the sub-sub windows. No idea why:
                            InvalidateRect(hwnd,&m_dispArea,FALSE);
                        }
                    }
                }
                return 0;
            }
        }
        return DefWindowProc(hwnd,message,wParam,lParam);
    }