wxWidgets / wxWidgets

Cross-Platform C++ GUI Library
https://www.wxwidgets.org/
6.18k stars 1.77k forks source link

wxAUI partial perspective restoration enhancement #12528

Open wxtrac opened 14 years ago

wxtrac commented 14 years ago

Issue migrated from trac ticket # 12528

component: wxAui | priority: normal | keywords: wxAui perspective restoration

2010-09-29 15:48:27: @lpoujoulat created the issue


I ran into the following problem with wxAUI perspective saving: in a multilingual application, I set the language to french and I save the perspective. Then I set the language to english and restore the perspective:

All the pane title come back to french because titles are also stored in the perspective string.

I then strip the title tag out of the persepective string before restoring: this time I got a blank title wheras I expected to have the titles left untouched.

To solve this, I made a small change to Load Perspective() that instead of setting a default value for missing perspective tags, leaves the corresponding item untouched in the panes. This way, it is now possible to partially restore panes.

Patch for this is attached

Regards

wxtrac commented 14 years ago

2010-09-29 15:48:43: @lpoujoulat uploaded file aui_persp_merging.patch (0.3 KiB)

wxtrac commented 14 years ago

2010-09-30 14:31:38: @vadz commented


I'm not sure to understand what is this about but it doesn't seem 2.8.12-critical. Is this issue 2.8-specific or does it also appear in 2.9 BTW?

As usual, any opinions from more AUI-aware people would be welcome.

wxtrac commented 14 years ago

2010-09-30 14:40:18: biwillia76 (Benjamin I. Williams) changed status from new to confirmed

2010-09-30 14:40:18: biwillia76 (Benjamin I. Williams) commented

This is definitely an issue. Does your patch solve the problem? I believe that a small change to the API is necessary to facilitate this, which precludes 2.8 as a milestone.

The issue is still in 2.9 and needs to be fixed.

wxtrac commented 14 years ago

2010-10-04 11:06:41: @lpoujoulat commented


Hello, sorry being late to answer,

First: it is not critical that the patch makes its way to 2.8.12, thus I'd like it, because I have to patch Aui a lot on our wxWidget compilation. But if you can't integrate it, I can live without it.

Second: yes, the patch solves the problem in an easy way; you just have to strip away unwanted tags form the perspective sting before loading it to avoid destroying the concerned attributes. I use regular expression for this:

wxRegEx del_captions(_T("caption=[^;]*;"));
del_captions.ReplaceAll(&layout_str, wxEmptyString);
frameManager.LoadPerspective(layout_str, false);

The only problem I see it that it relies on the perspective string format and it may not be guarantied in the future. What API change may you propose ?

wxtrac commented 8 years ago

2016-10-19 13:07:15: rozmansi (Simon Rozman) changed priority from low to normal

2016-10-19 13:07:15: rozmansi (Simon Rozman) commented

I have found this problem a pain in my side for a far too long time as well.

Rather than patching a few lines in wxWidgets, I made a workaround function to update captions in configuration string with current ones:

_/ Updates perspective captions with matching captions from panes._/
_/ \param[in   ] mgr          wxAUI manager_/ \param[inout] perspective  Perspective string to update captions in
_/_/ \returns
_/ - \c true when update succeeded_/ - \c false otherwise
_/
bool wxAuiManagerUpdatePerspectiveCaptions(wxAuiManager& mgr, wxString& perspective)
{
    wxString input = perspective;
    wxString part;

    // check layout string version
    //    'layout1' = wxAUI 0.9.0 - wxAUI 0.9.2
    //    'layout2' = wxAUI 0.9.2 (wxWidgets 2.8)
    part = input.BeforeFirst(wxT('|'));
    input = input.AfterFirst(wxT('|'));
    part.Trim(true);
    part.Trim(false);
    if (part != wxT("layout2"))
        return false;

    wxString result;
    result.Alloc(500);
    result = wxT('layout2|');

    // replace escaped characters so we can
    // split up the string easily
    input.Replace(wxT("\\|"), wxT("\a"));
    input.Replace(wxT("\\;"), wxT("\b"));

    while (1)
    {
        wxString pane_part = input.BeforeFirst(wxT('|'));
        input = input.AfterFirst(wxT('|'));
        pane_part.Trim(true);

        // if the string is empty, we're done parsing
        if (pane_part.empty())
            break;

        // Undo our escaping
        pane_part.Replace(wxT("\a"), wxT("|"));
        pane_part.Replace(wxT("\b"), wxT(";"));

        if (pane_part.Left(9) == wxT("dock_size"))
        {
            result += pane_part + wxT('|');
            continue;
        }

        wxAuiPaneInfo pane;
        mgr.LoadPaneInfo(pane_part, pane);

        wxAuiPaneInfo& p = mgr.GetPane(pane.name);
        if (!p.IsOk())
        {
            // the pane window couldn't be found
            // in the existing layout -- skip it
            continue;
        }

        // Update caption.
        pane.caption = p.caption;

        // Re-generate and append pane info.
        result += mgr.SavePaneInfo(pane) + wxT('|');
    }

    perspective = result;
    return true;
}

The following helper class demonstrates an example how to restore the wxAUI configuration:

#define wxPERSIST_AUIMGR_KIND "AuiManager"

// names for persistent options
#define wxPERSIST_AUIMGR_PERSPECTIVE "perspective"

_/
_/ Supports saving/restoring wxAuiManager state
///
class wxPersistentAuiManager : public wxPersistentObject
{
public:
    wxPersistentAuiManager(wxAuiManager *mgr) : wxPersistentObject(mgr)
    {
    }

    virtual wxString GetKind() const
    {
        return wxT(wxPERSIST_AUIMGR_KIND);
    }

    virtual wxString GetName() const
    {
        // Borrow the name of wxAguiManager from its window.
        return GetManager()->GetManagedWindow()->GetName();
    }

    virtual void Save() const
    {
        // Save perspective string to configuration.
        SaveValue(wxT(wxPERSIST_AUIMGR_PERSPECTIVE), GetManager()->SavePerspective());
    }

    virtual bool Restore()
    {
        // Load perspective string from configuration.
        wxString persp;
        wxCHECK(RestoreValue(wxT(wxPERSIST_AUIMGR_PERSPECTIVE), &persp), false);

        // Update captions (see http://trac.wxwidgets.org/ticket/12528).
        wxAuiManager* mgr = GetManager();
        wxCHECK(wxAuiManagerUpdatePerspectiveCaptions(*mgr, persp), false);

        // Restore perspective.
        return mgr->LoadPerspective(persp);
    }

protected:
    wxAuiManager *GetManager() const
    {
        return static_cast<wxAuiManager*>(GetObject());
    }

private:
    wxDECLARE_NO_COPY_CLASS(wxPersistentAuiManager);
};

_/
_/ wxAuiManager's instantiation of wxCreatePersistentObject template
///
inline wxPersistentObject *wxCreatePersistentObject(wxAuiManager *mgr)
{
    return new wxPersistentAuiManager(mgr);
}

I suggest the wxAuiManager::LoadPerspective() method to be extended to:

    bool LoadPerspective(const wxString& perspective, bool update # true, bool ignore_captionsfalse);

In wxAuiManager::LoadPerspective() method implementation before the p.SafeSet(pane); is called one should add:

    if (ignore_captions)
    {
        // Copy original caption before restoring pane info.
        pane.caption = p.caption;
    }

This solution would be: