aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornyamatongwe <devnull@localhost>2013-04-21 16:13:28 +1000
committernyamatongwe <devnull@localhost>2013-04-21 16:13:28 +1000
commit341e163afa67923ca42e083d176c726ea5ed5d3e (patch)
treecd5b0bc6f9bfd31848397972e4644a6ceb0b05ae
parentb4c56acc3db4184664ce16ea80cbe6ea8d806bf4 (diff)
downloadscintilla-mirror-341e163afa67923ca42e083d176c726ea5ed5d3e.tar.gz
Implement commonly needed folding methods based on code from SciTE.
-rw-r--r--doc/ScintillaDoc.html54
-rw-r--r--include/Scintilla.h7
-rw-r--r--include/Scintilla.iface17
-rw-r--r--src/Editor.cxx131
-rw-r--r--src/Editor.h10
5 files changed, 192 insertions, 27 deletions
diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html
index 44b7449b7..9621ea19e 100644
--- a/doc/ScintillaDoc.html
+++ b/doc/ScintillaDoc.html
@@ -5183,6 +5183,10 @@ sptr_t CallScintilla(unsigned int iMessage, uptr_t wParam, sptr_t lParam){
<a class="message" href="#SCI_GETFOLDEXPANDED">SCI_GETFOLDEXPANDED(int line)</a><br />
<a class="message" href="#SCI_CONTRACTEDFOLDNEXT">SCI_CONTRACTEDFOLDNEXT(int lineStart)</a><br />
<a class="message" href="#SCI_TOGGLEFOLD">SCI_TOGGLEFOLD(int line)</a><br />
+ <a class="message" href="#SCI_FOLDLINE">SCI_FOLDLINE(int line, int action)</a><br />
+ <a class="message" href="#SCI_FOLDCHILDREN">SCI_FOLDCHILDREN(int line, int action)</a><br />
+ <a class="message" href="#SCI_FOLDALL">SCI_FOLDALL(int action)</a><br />
+ <a class="message" href="#SCI_EXPANDCHILDREN">SCI_EXPANDCHILDREN(int line, int level)</a><br />
<a class="message" href="#SCI_ENSUREVISIBLE">SCI_ENSUREVISIBLE(int line)</a><br />
<a class="message" href="#SCI_ENSUREVISIBLEENFORCEPOLICY">SCI_ENSUREVISIBLEENFORCEPOLICY(int
line)</a><br />
@@ -5340,6 +5344,56 @@ sptr_t CallScintilla(unsigned int iMessage, uptr_t wParam, sptr_t lParam){
until you had finished. See <code>SciTEBase::FoldAll()</code> and
<code>SciTEBase::Expand()</code> for examples of the use of these messages.</p>
+ <p><b id="SCI_FOLDLINE">SCI_FOLDLINE(int line, int action)</b><br />
+ <b id="SCI_FOLDCHILDREN">SCI_FOLDCHILDREN(int line, int action)</b><br />
+ <b id="SCI_FOLDALL">SCI_FOLDALL(int action)</b><br />
+ These messages provide a higher-level approach to folding instead of setting expanded flags and showing
+ or hiding individual lines.</p>
+ <p>An individual fold can be contracted/expanded/toggled with <code>SCI_FOLDLINE</code>.
+ To affect all child folds as well call <code>SCI_FOLDCHILDREN</code>.</p>
+ <p>To affect the entire document call <code>SCI_FOLDALL</code>. With <code>SC_FOLDACTION_TOGGLE</code>
+ the first fold header in the document is examined to decide whether to expand or contract.
+ </p>
+ <table cellpadding="1" cellspacing="2" border="0" summary="Fold flags">
+ <tbody>
+ <tr>
+ <th align="left">Symbol</th>
+ <th align="left">Value</th>
+ <th align="left">Effect</th>
+ </tr>
+ </tbody>
+
+ <tbody valign="top">
+ <tr>
+ <td align="left">SC_FOLDACTION_CONTRACT</td>
+ <td align="left">0</td>
+ <td align="left">Contract.</td>
+ </tr>
+
+ <tr>
+ <td align="left">SC_FOLDACTION_EXPAND</td>
+ <td align="left">1</td>
+ <td align="left">Expand.</td>
+ </tr>
+
+ <tr>
+ <td align="left">SC_FOLDACTION_TOGGLE</td>
+ <td align="left">2</td>
+ <td align="left">Toggle between contracted and expanded.</td>
+ </tr>
+
+ </tbody>
+ </table>
+ <p></p>
+
+ <p><b id="SCI_EXPANDCHILDREN">SCI_EXPANDCHILDREN(int line, int level)</b><br />
+ This is used to respond to a change to a line causing its fold level or whether it is a header to change,
+ perhaps when adding or removing a '{'.</p>
+ <p>By the time the container has received the notification that the line has changed,
+ the fold level has already been set, so the container has to use the previous level in this call
+ so that any range hidden underneath this line can be shown.
+ </p>
+
<p><b id="SCI_CONTRACTEDFOLDNEXT">SCI_CONTRACTEDFOLDNEXT(int lineStart)</b><br />
Search efficiently for lines that are contracted fold headers.
This is useful when saving the user's folding when switching documents or saving folding with a file.
diff --git a/include/Scintilla.h b/include/Scintilla.h
index b175fc80f..e94672ebd 100644
--- a/include/Scintilla.h
+++ b/include/Scintilla.h
@@ -441,6 +441,13 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_SETFOLDEXPANDED 2229
#define SCI_GETFOLDEXPANDED 2230
#define SCI_TOGGLEFOLD 2231
+#define SC_FOLDACTION_CONTRACT 0
+#define SC_FOLDACTION_EXPAND 1
+#define SC_FOLDACTION_TOGGLE 2
+#define SCI_FOLDLINE 2237
+#define SCI_FOLDCHILDREN 2238
+#define SCI_EXPANDCHILDREN 2239
+#define SCI_FOLDALL 2662
#define SCI_ENSUREVISIBLE 2232
#define SC_FOLDFLAG_LINEBEFORE_EXPANDED 0x0002
#define SC_FOLDFLAG_LINEBEFORE_CONTRACTED 0x0004
diff --git a/include/Scintilla.iface b/include/Scintilla.iface
index b2e8608ff..416e628af 100644
--- a/include/Scintilla.iface
+++ b/include/Scintilla.iface
@@ -1110,6 +1110,23 @@ get bool GetFoldExpanded=2230(int line,)
# Switch a header line between expanded and contracted.
fun void ToggleFold=2231(int line,)
+enu FoldAction=SC_FOLDACTION
+val SC_FOLDACTION_CONTRACT=0
+val SC_FOLDACTION_EXPAND=1
+val SC_FOLDACTION_TOGGLE=2
+
+# Expand or contract a fold header.
+fun void FoldLine=2237(int line, int action)
+
+# Expand or contract a fold header and its children.
+fun void FoldChildren=2238(int line, int action)
+
+# Expand a fold header and all children. Use the level argument instead of the line's current level.
+fun void ExpandChildren=2239(int line, int level)
+
+# Expand or contract all fold headers.
+fun void FoldAll=2662(int action,)
+
# Ensure a particular line is visible by expanding any header line hiding it.
fun void EnsureVisible=2232(int line,)
diff --git a/src/Editor.cxx b/src/Editor.cxx
index c2731a1e3..15e221f29 100644
--- a/src/Editor.cxx
+++ b/src/Editor.cxx
@@ -6962,34 +6962,42 @@ void Editor::SetAnnotationVisible(int visible) {
/**
* Recursively expand a fold, making lines visible except where they have an unexpanded parent.
*/
-void Editor::Expand(int &line, bool doExpand) {
+int Editor::ExpandLine(int line) {
int lineMaxSubord = pdoc->GetLastChild(line);
line++;
while (line <= lineMaxSubord) {
- if (doExpand)
- cs.SetVisible(line, line, true);
+ cs.SetVisible(line, line, true);
int level = pdoc->GetLevel(line);
if (level & SC_FOLDLEVELHEADERFLAG) {
- if (doExpand && cs.GetExpanded(line)) {
- Expand(line, true);
+ if (cs.GetExpanded(line)) {
+ line = ExpandLine(line);
} else {
- Expand(line, false);
+ line = pdoc->GetLastChild(line);
}
- } else {
- line++;
}
+ line++;
+ }
+ return lineMaxSubord;
+}
+
+void Editor::SetFoldExpanded(int lineDoc, bool expanded) {
+ if (cs.SetExpanded(lineDoc, expanded)) {
+ RedrawSelMargin();
}
}
-void Editor::ToggleContraction(int line) {
+void Editor::FoldLine(int line, int action) {
if (line >= 0) {
- if ((pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) == 0) {
- line = pdoc->GetFoldParent(line);
- if (line < 0)
- return;
+ if (action == SC_FOLDACTION_TOGGLE) {
+ if ((pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) == 0) {
+ line = pdoc->GetFoldParent(line);
+ if (line < 0)
+ return;
+ }
+ action = (cs.GetExpanded(line)) ? SC_FOLDACTION_CONTRACT : SC_FOLDACTION_EXPAND;
}
- if (cs.GetExpanded(line)) {
+ if (action == SC_FOLDACTION_CONTRACT) {
int lineMaxSubord = pdoc->GetLastChild(line);
if (lineMaxSubord > line) {
cs.SetExpanded(line, 0);
@@ -7000,9 +7008,6 @@ void Editor::ToggleContraction(int line) {
// This does not re-expand the fold
EnsureCaretVisible();
}
-
- SetScrollBars();
- Redraw();
}
} else {
@@ -7011,11 +7016,35 @@ void Editor::ToggleContraction(int line) {
GoToLine(line);
}
cs.SetExpanded(line, 1);
- Expand(line, true);
- SetScrollBars();
- Redraw();
+ ExpandLine(line);
+ }
+
+ SetScrollBars();
+ Redraw();
+ }
+}
+
+void Editor::FoldExpand(int line, int action, int level) {
+ bool expanding = action == SC_FOLDACTION_EXPAND;
+ if (action == SC_FOLDACTION_TOGGLE) {
+ expanding = !cs.GetExpanded(line);
+ }
+ SetFoldExpanded(line, expanding);
+ if (expanding && (cs.HiddenLines() == 0))
+ // Nothing to do
+ return;
+ int lineMaxSubord = pdoc->GetLastChild(line, level & SC_FOLDLEVELNUMBERMASK);
+ line++;
+ cs.SetVisible(line, lineMaxSubord, expanding);
+ while (line <= lineMaxSubord) {
+ int levelLine = pdoc->GetLevel(line);
+ if (levelLine & SC_FOLDLEVELHEADERFLAG) {
+ SetFoldExpanded(line, expanding);
}
+ line++;
}
+ SetScrollBars();
+ Redraw();
}
int Editor::ContractedFoldNext(int lineStart) {
@@ -7057,7 +7086,7 @@ void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) {
EnsureLineVisible(lineParent, enforcePolicy);
if (!cs.GetExpanded(lineParent)) {
cs.SetExpanded(lineParent, 1);
- Expand(lineParent, true);
+ ExpandLine(lineParent);
}
}
SetScrollBars();
@@ -7086,6 +7115,44 @@ void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) {
}
}
+void Editor::FoldAll(int action) {
+ pdoc->EnsureStyledTo(pdoc->Length());
+ int maxLine = pdoc->LinesTotal();
+ bool expanding = action == SC_FOLDACTION_EXPAND;
+ if (action == SC_FOLDACTION_TOGGLE) {
+ // Discover current state
+ for (int lineSeek = 0; lineSeek < maxLine; lineSeek++) {
+ if (pdoc->GetLevel(lineSeek) & SC_FOLDLEVELHEADERFLAG) {
+ expanding = !cs.GetExpanded(lineSeek);
+ break;
+ }
+ }
+ }
+ if (expanding) {
+ cs.SetVisible(0, maxLine, true);
+ for (int line = 0; line < maxLine; line++) {
+ int levelLine = pdoc->GetLevel(line);
+ if (levelLine & SC_FOLDLEVELHEADERFLAG) {
+ SetFoldExpanded(line, true);
+ }
+ }
+ } else {
+ for (int line = 0; line < maxLine; line++) {
+ int level = pdoc->GetLevel(line);
+ if ((level & SC_FOLDLEVELHEADERFLAG) &&
+ (SC_FOLDLEVELBASE == (level & SC_FOLDLEVELNUMBERMASK))) {
+ SetFoldExpanded(line, false);
+ int lineMaxSubord = pdoc->GetLastChild(line, -1);
+ if (lineMaxSubord > line) {
+ cs.SetVisible(line + 1, lineMaxSubord, false);
+ }
+ }
+ }
+ }
+ SetScrollBars();
+ Redraw();
+}
+
int Editor::GetTag(char *tagValue, int tagNumber) {
const char *text = 0;
int length = 0;
@@ -8533,9 +8600,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
return cs.HiddenLines() ? 0 : 1;
case SCI_SETFOLDEXPANDED:
- if (cs.SetExpanded(wParam, lParam != 0)) {
- RedrawSelMargin();
- }
+ SetFoldExpanded(wParam, lParam != 0);
break;
case SCI_GETFOLDEXPANDED:
@@ -8547,7 +8612,23 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
break;
case SCI_TOGGLEFOLD:
- ToggleContraction(wParam);
+ FoldLine(wParam, SC_FOLDACTION_TOGGLE);
+ break;
+
+ case SCI_FOLDLINE:
+ FoldLine(wParam, lParam);
+ break;
+
+ case SCI_FOLDCHILDREN:
+ FoldExpand(wParam, lParam, pdoc->GetLevel(wParam));
+ break;
+
+ case SCI_FOLDALL:
+ FoldAll(wParam);
+ break;
+
+ case SCI_EXPANDCHILDREN:
+ FoldExpand(wParam, SC_FOLDACTION_EXPAND, lParam);
break;
case SCI_CONTRACTEDFOLDNEXT:
diff --git a/src/Editor.h b/src/Editor.h
index 4e6c7aee9..935fe1513 100644
--- a/src/Editor.h
+++ b/src/Editor.h
@@ -569,10 +569,16 @@ protected: // ScintillaBase subclass needs access to much of Editor
void SetAnnotationVisible(int visible);
- void Expand(int &line, bool doExpand);
- void ToggleContraction(int line);
+ int ExpandLine(int line);
+ void SetFoldExpanded(int lineDoc, bool expanded);
+ void FoldLine(int line, int action);
+ void FoldExpand(int line, int action, int level);
int ContractedFoldNext(int lineStart);
void EnsureLineVisible(int lineDoc, bool enforcePolicy);
+ void FoldChanged(int line, int levelNow, int levelPrev);
+ void NeedShown(int pos, int len);
+ void FoldAll(int action);
+
int GetTag(char *tagValue, int tagNumber);
int ReplaceTarget(bool replacePatterns, const char *text, int length=-1);