News:

When registered with our forums, feel free to send a "here I am" post here to differ human beings from SPAM bots.

Main Menu

Feature Request: Code Folding by Level Shortcuts

Started by javmss, November 17, 2009, 02:10:34 PM

Previous topic - Next topic

javmss

on
In November 06, 2009 I have previously posted this topic:
  Code::Blocks > User forums > Using Code::Blocks > Feature Request: Code Folding by Level Shortcuts

Since I got no answer, I thing it might be in the wrong place, so I am reposting it here.
I apologise if I'm being inconvenient.
--------------------------------------------------------------------------------

Notepad++ (http://notepad-plus.sourceforge.net/) has a very usefull feature that allows me to selectively fold all given levels by the respective keyboard shortcut.

If I want to fold all "level 3" blocks in a file (C, C++, XML, whatever), I just need to "ALT+3". To unfold, "SHIFT+ALT+3".
I can do this to anything between level 0 to level 9 (the number in my keyboard end on 9, unfortunately).

In Code::Blocks all I have (at least from what I know) is "fold/unfold current block" or "fold/unfold absolutely all existing blocks in my file".

Is there any chance to have a similar feature in Code::Blocks please???

ollydbg

hi, javmss.

Currently, I don't have much time to help you, but I can give you the direction: the source code of cbeditor.cpp, which is located in:
svn\src\sdk\cbeditor.cpp
the related code was located from line 1924-2024. So, you can simply add some modification to these code, and do the folding function as you wanted.


void cbEditor::DoFoldAll(int fold)
{
    cbAssert(m_pControl);
    if (m_SplitType != stNoSplit)
        cbAssert(m_pControl2);
    cbStyledTextCtrl* ctrl = GetControl();
    ctrl->Colourise(0, -1); // the *most* important part!
    int count = ctrl->GetLineCount();
    for (int i = 0; i <= count; ++i)
        DoFoldLine(i, fold);
}

void cbEditor::DoFoldBlockFromLine(int line, int fold)
{
    cbAssert(m_pControl);
    if (m_SplitType != stNoSplit)
        cbAssert(m_pControl2);
    cbStyledTextCtrl* ctrl = GetControl();
    ctrl->Colourise(0, -1); // the *most* important part!
    int i, parent, maxLine, level, UnfoldUpto = line;
    bool FoldedInside = false;

    parent = ctrl->GetFoldParent(line);
    level = ctrl->GetFoldLevel(parent);
    /* The following code will check if the child is hidden
    *  under parent before unfolding it
    */
    if (fold == 0)
    {
        do
        {
            if (!ctrl->GetFoldExpanded(parent))
            {
                FoldedInside = true;
                UnfoldUpto = parent;
            }
            if (wxSCI_FOLDLEVELBASE == (level & wxSCI_FOLDLEVELNUMBERMASK))
                break;
            parent = ctrl->GetFoldParent(parent);
            level = ctrl->GetFoldLevel(parent);
        }
        while (parent != -1);
    }

    maxLine = ctrl->GetLastChild(line, -1);

    for (i = UnfoldUpto; i <= maxLine; ++i)
        DoFoldLine(i, fold);
}

bool cbEditor::DoFoldLine(int line, int fold)
{
    cbAssert(m_pControl);
    if (m_SplitType != stNoSplit)
        cbAssert(m_pControl2);
    cbStyledTextCtrl* ctrl = GetControl();
    int level = ctrl->GetFoldLevel(line);

    // The fold parameter is the type of folding action requested
    // 0 = Unfold; 1 = Fold; 2 = Toggle folding.

    // Check if the line is a header (fold point).
    if (level & wxSCI_FOLDLEVELHEADERFLAG)
    {
        bool IsExpanded = ctrl->GetFoldExpanded(line);

        // If a fold/unfold request is issued when the block is already
        // folded/unfolded, ignore the request.
        if (fold == 0 && IsExpanded) return true;
        if (fold == 1 && !IsExpanded) return true;

        // Apply the folding level limit only if the current block will be
        // folded (that means it's currently expanded), folding level limiter
        // must be enabled of course. Unfolding will not be affected.
        if (m_pData->mFoldingLimit && IsExpanded)
        {
            if ((level & wxSCI_FOLDLEVELNUMBERMASK) > (wxSCI_FOLDLEVELBASE + m_pData->mFoldingLimitLevel-1))
                return false;
        }

        ctrl->ToggleFold(line);
        return true;
    }
    return false;
}

void cbEditor::FoldAll()
{
    DoFoldAll(1);
}

void cbEditor::UnfoldAll()
{
    DoFoldAll(0);
}

void cbEditor::ToggleAllFolds()
{
    DoFoldAll(2);
}
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

javmss

I don't have much knowledge about the C::B SDK, so I took a look to the code where you told me and realised I'd do something like this:


/** Fold/Unfold/Toggle all folds in the givel level.
\param level Level number of folding, starting from 0.
\param fold Type of folding action requested: \n
- 0 = Unfold.
- 1 = Fold.
- 2 = Toggle folding. */
void cbEditor::DoFoldAllAtLevel(int level, int fold)
{
    cbAssert(m_pControl);
    if (m_SplitType != stNoSplit)
        cbAssert(m_pControl2);

    cbStyledTextCtrl* ctrl = GetControl();
    ctrl->Colourise(0, -1); // the *most* important part!

// Scan all file lines searching for the specified folding level.
    int count = ctrl->GetLineCount();
    for (int line = 0; line <= count; ++line)
    {
int parent = ctrl->GetFoldParent(line);

if ( level == ctrl->GetFoldLevel(parent) ) // Found on fold in "level".
{
int maxLine = ctrl->GetLastChild(line, -1);

for (i = line; i <= maxLine; ++i)
DoFoldLine(i, fold);
}
    }
}


Now I wonder how can I bind this to different shortcuts.
I can suppose that I should create several "FoldAt#( )" methods, but I can't catch how to bind it to the "ALT+#" keys...

I will be looking for it, but I'd be very glad for a clue.

Tanks!

dmoore

maybe I can incorporate this into my editor tweaks plugin. http://forums.next.codeblocks.org/index.php/topic,11660.0.html

QuoteNow I wonder how can I bind this to different shortcuts.

once you have added menu entries, the keybinder plugin will let you set shortcuts for it
Python plugins: [url="https://github.com/spillz/codeblocks-python"]https://github.com/spillz/codeblocks-python[/url]
Code::Blocks Daily Builds -- Ubuntu PPA: [url="https://launchpad.net/~damien-moore/+archive/codeblocks"]https://launchpad.net/~damien-moore/+archive/codeblocks[/url]

dmoore

#4
btw, your code doesn't do what you think it does (GetFoldLevel returns a more complicated result). Also, I've no idea why you have the nested loop.

In addition I'm not even sure what you are trying to achieve. I assume you want options to fold all code above a certain fold level? If so, I propose:


//fold: 0 = unfold, 1 = fold
void EditorTweaks::DoFoldAboveLevel(int level, int fold)
{
   cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
   if(!ed || !ed->GetControl())
       return;

   level+=wxSCI_FOLDLEVELBASE;

   ed->GetControl()->Colourise(0, -1); // the *most* important part!

   int count = ed->GetControl()->GetLineCount();
   for (int line = 0; line <= count; ++line)
   {
       int line_level_data = ed->GetControl()->GetFoldLevel(line);
       if (!(line_level_data & wxSCI_FOLDLEVELHEADERFLAG))
           continue;
       int line_level = line_level_data & wxSCI_FOLDLEVELNUMBERMASK;

       bool IsExpanded = ed->GetControl()->GetFoldExpanded(line);

       // If a fold/unfold request is issued when the block is already
       // folded/unfolded, ignore the request.
       if(line_level<=level)
           if(IsExpanded)
               continue;
       else
           if(fold==0 && IsExpanded || fold ==1 && !IsExpanded)
               continue;
       ed->GetControl()->ToggleFold(line);
   }
}


this code is now part of editor tweaks:


svn checkout http://svn.berlios.de/svnroot/repos/cbilplugin/branches/EditorTweaks
Python plugins: [url="https://github.com/spillz/codeblocks-python"]https://github.com/spillz/codeblocks-python[/url]
Code::Blocks Daily Builds -- Ubuntu PPA: [url="https://launchpad.net/~damien-moore/+archive/codeblocks"]https://launchpad.net/~damien-moore/+archive/codeblocks[/url]

MortenMacFly

Just for the record: I think the idea behind the aligner plugin would fit very well into this plugin, too. How about that?

See here: http://forums.next.codeblocks.org/index.php/topic,11274.msg79225.html#msg79225
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: [url="https://www.codeblocks.org/docs/main_codeblocks_en.html"]https://www.codeblocks.org/docs/main_codeblocks_en.html[/url]
C::B FAQ: [url="https://wiki.codeblocks.org/index.php?title=FAQ"]https://wiki.codeblocks.org/index.php?title=FAQ[/url]