Code::Blocks Forums

Developer forums (C::B DEVELOPMENT STRICTLY!) => Contributions to C::B => Topic started by: javmss on November 17, 2009, 02:10:34 pm

Title: Feature Request: Code Folding by Level Shortcuts
Post by: javmss on November 17, 2009, 02:10:34 pm
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???
Title: Re: Feature Request: Code Folding by Level Shortcuts
Post by: ollydbg on November 17, 2009, 04:48:14 pm
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.

Code
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);
}
Title: Re: Feature Request: Code Folding by Level Shortcuts
Post by: javmss on December 16, 2009, 07:18:58 pm
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:

Code
/**	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!
Title: Re: Feature Request: Code Folding by Level Shortcuts
Post by: dmoore on December 16, 2009, 07:40:28 pm
maybe I can incorporate this into my editor tweaks plugin. http://forums.codeblocks.org/index.php/topic,11660.0.html

Quote
Now 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
Title: Re: Feature Request: Code Folding by Level Shortcuts
Post by: dmoore on December 16, 2009, 10:15:26 pm
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:

Code
//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:

Code
svn checkout http://svn.berlios.de/svnroot/repos/cbilplugin/branches/EditorTweaks
Title: Re: Feature Request: Code Folding by Level Shortcuts
Post by: MortenMacFly on December 17, 2009, 07:57:12 am
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.codeblocks.org/index.php/topic,11274.msg79225.html#msg79225