Author Topic: Improvement in TabSwitcher  (Read 20943 times)

Offline Alatar

  • Multiple posting newcomer
  • *
  • Posts: 59
Improvement in TabSwitcher
« on: September 28, 2009, 12:15:59 pm »
I modify MainFrame and EditorManager code to add stack-based tab switching to switcher dialog. I think this is more useful and handy then using Alt+Left/Right.
This code may work wrong, but I hope in most cases it would be helpful. I think, this is temporary solution until wxAuiNotebook would be improved.
Modified files in attachments.

[attachment deleted by admin]

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Improvement in TabSwitcher
« Reply #1 on: January 09, 2010, 07:37:31 am »
I have get and apply this patch.
It look working fine. I this it will be better to let old switching tab code, make new one with your source code (into main frame) and adding a command to see it into keyboard managment.
It is really cool to have this possibility for switching tab. Congratulation.
I think it is an evolution really important for Code::Blocks.

If we have a green light to say, ok it will be integrated into official version, I agree to help you to make evolution on it.
« Last Edit: January 09, 2010, 07:51:32 am by Feneck91 »

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Improvement in TabSwitcher
« Reply #2 on: January 10, 2010, 10:44:37 pm »
It's not work if you press CTRL + SHIFT + ALT : taking previous tab in tab order, not in stack base tabs order.

Offline Alatar

  • Multiple posting newcomer
  • *
  • Posts: 59
Re: Improvement in TabSwitcher
« Reply #3 on: January 10, 2010, 11:59:44 pm »
Try to press CTRL+TAB and then (don`t release CTRL) press SHIFT and again TAB.

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Improvement in TabSwitcher
« Reply #4 on: January 11, 2010, 07:25:00 am »
Yes, I know that ! I think CTRL + SHIFT + ALT directly have no sense...
I don't know why this patch is not into official codeblocks source code, but I'll work on your patch to propose another patch with new shortcut like "Switch Tabs Stack". Do you agree ?
« Last Edit: January 11, 2010, 02:07:44 pm by Feneck91 »

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Improvement in TabSwitcher
« Reply #5 on: January 12, 2010, 07:53:23 am »
To have a change to figure into official Code::Blocks IDE, I have patch your source code :
Change some variable name (Added type, long name).
And I have added a new menu entry into view menu : Switch tabs stack.
Now, the user can choose between current way change to edited file or new one with Switch tabs stack.
This new menu entry is now into shortcut too: The user can change CTRL+TAB shortcut to new Switch tabs stack.
I hope you have correctly tested your source code because I don't test it (new / delete), its seem work fine.
I'll use it intensively for 2 months with 2 developpers for a professionnal project.
We must work together to make your patch into official Code::Blocks IDE : it is awful to work without this patch, its seems very important to me.

Patch :
Code: [Select]
Index: src/include/editormanager.h
===================================================================
--- src/include/editormanager.h (revision 6077)
+++ src/include/editormanager.h (working copy)
@@ -45,6 +45,20 @@
 struct cbFindReplaceData;
 
 /*
+ * Struct for store tabs stack info
+ */
+struct cbNotebookStack
+{
+    cbNotebookStack(wxWindow* a_pWindow = NULL)
+        : m_pWindow (a_pWindow),
+          m_pNextNotebookStack (NULL)
+    {}
+
+    wxWindow*           m_pWindow;
+    cbNotebookStack*    m_pNextNotebookStack;
+};
+
+/*
  * No description
  */
 class DLLIMPORT EditorManager : public Mgr<EditorManager>, public wxEvtHandler
@@ -59,6 +73,7 @@
         virtual void operator=(const EditorManager& rhs){ cbThrow(_T("Can't assign an EditorManager* !!!")); }
 
         wxAuiNotebook* GetNotebook(){ return m_pNotebook; }
+        cbNotebookStack* GetNotebookStack();
         void CreateMenu(wxMenuBar* menuBar);
         void ReleaseMenu(wxMenuBar* menuBar);
         void Configure();
@@ -174,6 +189,9 @@
         wxFileName FindHeaderSource(const wxArrayString& candidateFilesArray, const wxFileName& activeFile, bool& isCandidate);
 
         wxAuiNotebook* m_pNotebook;
+        cbNotebookStack* m_pNotebookStackHead;
+        cbNotebookStack* m_pNotebookStackTail;
+        size_t m_nNotebookStackSize;
         cbFindReplaceData* m_LastFindReplaceData;
         EditorColourSet* m_Theme;
         ListCtrlLogger* m_pSearchLog;
Index: src/sdk/editormanager.cpp
===================================================================
--- src/sdk/editormanager.cpp (revision 6077)
+++ src/sdk/editormanager.cpp (working copy)
@@ -156,6 +156,9 @@
 
 EditorManager::EditorManager()
         : m_pNotebook(0L),
+        m_pNotebookStackHead(new cbNotebookStack),
+        m_pNotebookStackTail(m_pNotebookStackHead),
+        m_nNotebookStackSize(0),
         m_LastFindReplaceData(0L),
         m_pSearchLog(0),
         m_SearchLogIndex(-1),
@@ -192,6 +195,55 @@
     Manager::Get()->GetConfigManager(_T("editor"))->Write(_T("/zoom"), m_zoom);
 }
 
+cbNotebookStack* EditorManager::GetNotebookStack()
+{
+    bool bFounded = false;
+    wxWindow* pWindow;
+    cbNotebookStack* pNotebookStack;
+    cbNotebookStack* pPrevNotebookStack;
+
+    while(m_nNotebookStackSize != m_pNotebook->GetPageCount()) //Sync stack with Notebook
+    {
+        if(m_nNotebookStackSize < m_pNotebook->GetPageCount())
+        {
+            for(size_t i = 0; i<m_pNotebook->GetPageCount(); ++i)
+            {
+                pWindow = m_pNotebook->GetPage(i);
+                bFounded = false;
+                for (pNotebookStack = m_pNotebookStackHead->m_pNextNotebookStack; pNotebookStack != NULL; pNotebookStack = pNotebookStack->m_pNextNotebookStack)
+                {
+                    if(pWindow == pNotebookStack->m_pWindow)
+                    {
+                        bFounded = true;
+                        break;
+                    }
+                }
+                if(!bFounded)
+                {
+                    m_pNotebookStackTail->m_pNextNotebookStack = new cbNotebookStack(pWindow);
+                    m_pNotebookStackTail = m_pNotebookStackTail->m_pNextNotebookStack;
+                    ++m_nNotebookStackSize;
+                }
+            }
+        }
+        if(m_nNotebookStackSize > m_pNotebook->GetPageCount())
+        {
+            for (pPrevNotebookStack = m_pNotebookStackHead, pNotebookStack = pPrevNotebookStack->m_pNextNotebookStack; pNotebookStack != NULL; pPrevNotebookStack = pNotebookStack, pNotebookStack = pNotebookStack->m_pNextNotebookStack)
+            {
+                if(m_pNotebook->GetPageIndex(pNotebookStack->m_pWindow) == wxNOT_FOUND)
+                {
+                    pPrevNotebookStack->m_pNextNotebookStack = pNotebookStack->m_pNextNotebookStack;
+                    delete pNotebookStack;
+                    --m_nNotebookStackSize;
+                    pNotebookStack = pPrevNotebookStack;
+                }
+            }
+        }
+    }
+
+    return m_pNotebookStackHead->m_pNextNotebookStack;
+}
+
 void EditorManager::CreateMenu(wxMenuBar* menuBar)
 {
 }
@@ -2510,6 +2562,32 @@
     CodeBlocksEvent evt(cbEVT_EDITOR_ACTIVATED, -1, 0, eb);
     Manager::Get()->GetPluginManager()->NotifyPlugins(evt);
 
+    wxWindow* pWindow;
+    cbNotebookStack* pNotebookStack;
+    cbNotebookStack* pPrevNotebookStack;
+    pWindow = m_pNotebook->GetPage(event.GetSelection());
+    for (pPrevNotebookStack = m_pNotebookStackHead, pNotebookStack = pPrevNotebookStack->m_pNextNotebookStack; pNotebookStack != NULL; pPrevNotebookStack = pNotebookStack, pNotebookStack = pNotebookStack->m_pNextNotebookStack)
+    {
+        if(pWindow == pNotebookStack->m_pWindow)
+        {
+            if(m_pNotebookStackTail == pNotebookStack)
+            {
+                m_pNotebookStackTail = pPrevNotebookStack;
+            }
+            pPrevNotebookStack->m_pNextNotebookStack = pNotebookStack->m_pNextNotebookStack;
+            pNotebookStack->m_pNextNotebookStack = m_pNotebookStackHead->m_pNextNotebookStack;
+            m_pNotebookStackHead->m_pNextNotebookStack = pNotebookStack;
+            break;
+        }
+    }
+    if((m_pNotebookStackHead->m_pNextNotebookStack == NULL)||(pWindow != m_pNotebookStackHead->m_pNextNotebookStack->m_pWindow))
+    {
+        pNotebookStack = new cbNotebookStack(pWindow);
+        pNotebookStack->m_pNextNotebookStack = m_pNotebookStackHead->m_pNextNotebookStack;
+        m_pNotebookStackHead->m_pNextNotebookStack = pNotebookStack;
+        ++m_nNotebookStackSize;
+    }
+
     // focus editor on next update event
     m_pData->m_SetFocusFlag = true;
 
@@ -2539,6 +2617,21 @@
         if (!QueryClose(eb))
             event.Veto();
     }
+
+    wxWindow* pWindow;
+    cbNotebookStack* pNotebookStack;
+    cbNotebookStack* pPrevNotebookStack;
+    pWindow = m_pNotebook->GetPage(event.GetSelection());
+    for (pPrevNotebookStack = m_pNotebookStackHead, pNotebookStack = pPrevNotebookStack->m_pNextNotebookStack; pNotebookStack != NULL; pPrevNotebookStack = pNotebookStack, pNotebookStack = pNotebookStack->m_pNextNotebookStack)
+    {
+        if(pWindow == pNotebookStack->m_pWindow)
+        {
+            pPrevNotebookStack->m_pNextNotebookStack = pNotebookStack->m_pNextNotebookStack;
+            delete pNotebookStack;
+            --m_nNotebookStackSize;
+            break;
+        }
+    }
     event.Skip(); // allow others to process it too
 }
 
Index: src/src/main.cpp
===================================================================
--- src/src/main.cpp (revision 6077)
+++ src/src/main.cpp (working copy)
@@ -211,6 +211,7 @@
 int idViewScriptConsole = XRCID("idViewScriptConsole");
 int idViewFocusEditor = XRCID("idViewFocusEditor");
 int idViewSwitchTabs = XRCID("idViewSwitchTabs");
+int idViewSwitchTabsStack = XRCID("idViewSwitchTabsStack");
 int idViewFullScreen = XRCID("idViewFullScreen");
 
 int idSearchFind = XRCID("idSearchFind");
@@ -431,6 +432,7 @@
     EVT_MENU(idViewScriptConsole, MainFrame::OnViewScriptConsole)
     EVT_MENU(idViewFocusEditor, MainFrame::OnFocusEditor)
     EVT_MENU(idViewSwitchTabs, MainFrame::OnSwitchTabs)
+    EVT_MENU(idViewSwitchTabsStack, MainFrame::OnSwitchTabsStack)
     EVT_MENU(idViewFullScreen, MainFrame::OnToggleFullScreen)
 
     EVT_MENU(idSettingsEnvironment, MainFrame::OnSettingsEnvironment)
@@ -4048,6 +4050,68 @@
     }
 }
 
+void MainFrame::OnSwitchTabsStack(wxCommandEvent& event)
+{
+    size_t index = 0;
+    // Get the notebook from the editormanager:
+    wxAuiNotebook* nb = Manager::Get()->GetEditorManager()->GetNotebook();
+    if (!nb)
+        return;
+    cbNotebookStack* pNotebookStack;
+
+    // Create container and add all open editors:
+    wxSwitcherItems items;
+    items.AddGroup(_("Open files"), wxT("editors"));
+    for (pNotebookStack = Manager::Get()->GetEditorManager()->GetNotebookStack() ; pNotebookStack != NULL; pNotebookStack = pNotebookStack->m_pNextNotebookStack)
+    {
+        wxWindow* window = pNotebookStack->m_pWindow;
+        if(nb->GetPageIndex(window) == wxNOT_FOUND)
+            continue;
+        index = nb->GetPageIndex(window);
+        wxString title = nb->GetPageText(index);
+
+        items.AddItem(title, title, index, nb->GetPageBitmap(index)).SetWindow(window);
+    }
+
+    // Select the focused editor:
+    if(items.GetItemCount() > 2)
+    {   // CTRL + TAB directly select the last editor, not the current one
+        items.SetSelection(2);
+    }
+    else
+    {
+        items.SetSelection(items.GetItemCount()-1);
+    }
+
+    // Create the switcher dialog
+    wxSwitcherDialog dlg(items, wxGetApp().GetTopWindow());
+
+    // Ctrl+Tab workaround for non windows platforms:
+    if (platform::cocoa)
+    {
+        dlg.SetModifierKey(WXK_ALT);
+    }
+    else if (platform::gtk)
+    {
+        dlg.SetExtraNavigationKey(wxT(','));
+    }
+
+    // Finally show the dialog:
+    int answer = dlg.ShowModal();
+
+    // If necessary change the selected editor:
+    if ((answer == wxID_OK) && (dlg.GetSelection() != -1))
+    {
+        wxSwitcherItem& item = items.GetItem(dlg.GetSelection());
+        wxWindow* win = item.GetWindow();
+        if(win)
+        {
+            nb->SetSelection(item.GetId());
+            win->SetFocus();
+        }
+    }
+}
+
 void MainFrame::OnToggleFullScreen(wxCommandEvent& event)
 {
     ShowFullScreen( !IsFullScreen(), wxFULLSCREEN_NOTOOLBAR// | wxFULLSCREEN_NOSTATUSBAR
Index: src/src/main.h
===================================================================
--- src/src/main.h (revision 6077)
+++ src/src/main.h (working copy)
@@ -180,6 +180,7 @@
         void OnToggleStatusBar(wxCommandEvent& event);
         void OnFocusEditor(wxCommandEvent& event);
         void OnSwitchTabs(wxCommandEvent& event);
+        void OnSwitchTabsStack(wxCommandEvent& event);
         void OnToggleFullScreen(wxCommandEvent& event);
 
         // plugin events
Index: src/src/resources/main_menu.xrc
===================================================================
--- src/src/resources/main_menu.xrc (revision 6077)
+++ src/src/resources/main_menu.xrc (working copy)
@@ -538,6 +538,10 @@
         <accel>Ctrl+Tab</accel>
         <help>Switch between open editor tabs</help>
       </object>
+      <object class="wxMenuItem" name="idViewSwitchTabsStack">
+        <label>Switch tabs stack</label>
+        <help>Switch between open editor tabs with sorting of previous used documents</help>
+      </object>
     </object>
     <object class="wxMenu" name="menu_search">
       <label>Sea&amp;rch</label>

How to propose this patch and how to get feed back to know why it is refused and what shall we do to make it accepted ?
This patch has advantage to let the current way of tab changing, just added new one. (yours).

Thanks to give me your feedback.
Feneck91

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9528
Re: Improvement in TabSwitcher
« Reply #6 on: January 12, 2010, 08:33:31 am »
How to propose this patch and how to get feed back to know why it is refused and what shall we do to make it accepted ?
Via the patch tracker here:
http://developer.berlios.de/patch/?group_id=5358

The original patch is here:
http://developer.berlios.de/patch/?func=detailpatch&patch_id=2902&group_id=5358

Once it got assigned you will get an email automatically if something changes. You can also subscribe to other patches.

Please post a comment in the original patch and/or update the patch there accordingly (only possible with the help of alatar_).

BTW: You'll need to register with BerliOS to have an account which is needed to post patches / bugs.
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: http://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: http://wiki.codeblocks.org/index.php?title=FAQ

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Improvement in TabSwitcher
« Reply #7 on: January 12, 2010, 09:15:36 am »
Alastar, are you agree to work together ?
I let you test my patch and accept or refuse it.

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9528
Re: Improvement in TabSwitcher
« Reply #8 on: January 12, 2010, 09:15:47 am »
Change some variable name (Added type, long name).
And I have added a new menu entry into view menu : Switch tabs stack.
This is not the default for the CTRL+TAB shortcut. Is this on purpose? I guess it'd be more intuitive if it would. So the other option become an... erm... option.
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: http://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: http://wiki.codeblocks.org/index.php?title=FAQ

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Improvement in TabSwitcher
« Reply #9 on: January 12, 2010, 09:55:29 am »
I'm french, I don't know what is erm option ... is it means obsolet ?
I don't know why Alatar patch is not validate into Code:Blocks...
So, 3 differents ways :
1> Replace the actual CTRL+TAB with a new one with stack recording. The old way was also not supported. This is the alatar patch.
2> Let the current CTRL+TAB working like it actually works and propose another way, the user can custumize with shortcut and so, replace actual CTRL+TAB working by new one. This is my patch.
3> Let the current CTRL+TAB working like it actually works but remove its shortcut and assign it to new working. If the user want to keep old way of CTRL+TAB, he can custumize shortcut to old way. I can do this patch if you want, but I'm not sure that only modify xrc will work if the user has assign another key to this shortcut.

I thought that if this patch was not into Code::Blocks it was because we should not modify currents working of Code::Blocks, so why I propose the patch (2).

What shall we do ?

Offline MortenMacFly

  • Administrator
  • Lives here!
  • *****
  • Posts: 9528
Re: Improvement in TabSwitcher
« Reply #10 on: January 12, 2010, 10:07:13 am »
What shall we do ?
I'd vote for 3>.

I've modified the patch again to make re-use of duplicate code and format it a bit. (BTW: I absolutely don't like initialisation of variables in the for () block btw...). The state of the patch in "pending" (being processed). The reason is simple: Its untested under Linux. Once this is done it may make it into trunk. That's very likely from my point of view hence the other devs can object.
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: http://www.codeblocks.org/docs/main_codeblocks_en.html
C::B FAQ: http://wiki.codeblocks.org/index.php?title=FAQ

Offline jens

  • Administrator
  • Lives here!
  • *****
  • Posts: 7265
    • Jens' unofficial debian-repository for the Code::Blocks - IDE
Re: Improvement in TabSwitcher
« Reply #11 on: January 12, 2010, 10:24:37 am »
I vote for keeping the Ctrl + Tab behaviour as it is by default and change it only if the user wants it.

Two causes for this:

1. changing an existing behaviour is normally not a good idea and can confuse other users and will most likely lead to "bug"-reports,

2. the default for Ctrl+[Shift+]Tab in most applications is to switch between the tabs directly and not to switch between the tabs accessed as last.

@Martin: it would be nice, if you can send me your cleaned up patch to test it on linux.

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Improvement in TabSwitcher
« Reply #12 on: January 12, 2010, 10:45:29 am »
I agree with jens, I think, let the user take the decision of way of changing documents by pressing CTRL + TAB.
It was why I propose the second patch.
Quote
2. the default for Ctrl+[Shift+]Tab in most applications is to switch between the tabs directly and not to switch between the tabs accessed as last.
Not true, Visual C++ / Netbeans work like this, last accessed, first on tab order...
Quote
@Martin: it would be nice, if you can send me your cleaned up patch to test it on linux.
I have modified the source code to be more understanding, if you have patched this source, please post the new version.

Thanks.

Nb : Some problems could occurs with the function void MainFrame::CreateMenubar()
Quote
   // Ctrl+Tab workaround for non windows platforms:
    if ((platform::carbon) || (platform::gtk))
    {
        // Find the menu item for tab switching:
        tmpidx = mbar->FindMenu(_("&View"));
        if (tmpidx != wxNOT_FOUND)
        {
            wxMenu* view = mbar->GetMenu(tmpidx);
            wxMenuItem* switch_item = view->FindItem(idViewSwitchTabs);
            if (switch_item)
            {
                // Change the accelerator for this menu item:
                wxString accel;
                if (platform::carbon)
                    accel = wxT("Alt+Tab");
                else if (platform::gtk)
                    accel = wxT("Ctrl+,");
                switch_item->SetItemLabel(wxString(_("S&witch Tabs")) + wxT("\t") + accel);
            }
        }
    }
What shall we do here ? Testing on wich switching tab type the accel is for and modify it and only it ? Or let it like this and accelerators will overwrite it if the shortcut is modified ?

Thanks for your reply.

Offline Alatar

  • Multiple posting newcomer
  • *
  • Posts: 59
Re: Improvement in TabSwitcher
« Reply #13 on: January 12, 2010, 06:51:04 pm »
Alastar, are you agree to work together ?
I let you test my patch and accept or refuse it.
Agree of course. I try to help with further improvement patch.
I'd vote for 3>.
I`m too.
Morten, where is last version of this patch?
Feneck91, I think, there is not good idea to add it into menu - it must be in Settings->Invironment, where it was before migrating from wxFlatNotebook to wxAuiNotebook.

Offline Feneck91

  • Multiple posting newcomer
  • *
  • Posts: 112
Re: Improvement in TabSwitcher
« Reply #14 on: January 12, 2010, 07:53:17 pm »
I'd vote for 4 !
4> I think like you : let only one menu / shortcut, but add an option to know how to manage tabs :
- Could add into : Setting / Editor... / General Setting .... but where put this option ?
- Could add into : Setting / Environment ... / General Setting .... but where put this option ? After Allow only one running instance or in Notebook appearance.
If you reply, I could make the patch !


I think it is the better solution. question is : where whe should put this option, and how describe it ?

Morten, where is last version of this patch ?