6
$\begingroup$

If you have a notebook with lot of content open you will see a scroll bar on the far right and bottom. I'm looking for a function that will return the current value of of the scroll bars. I'd also like to be able to set the value of the scroll bars with a function call.

In a pane, there is a ScrollPosition option which allows you to set both scroll positions to an ordered pair like {500,600}. However, I don't see an option for the entire notebook.

Does anyone know of a way to do this?

$\endgroup$
1
  • 1
    $\begingroup$ There are some tokens related to scrolling but it seems with not ability to set a specific value. You may consider putting CellTags in some places where you can easily NotebookLocate to. $\endgroup$
    – Kuba
    Nov 26, 2015 at 7:31

1 Answer 1

1
$\begingroup$

I don't think directly getting/setting the scroll position from a function is possible within Mathematica alone. You could conceivably call external programs to screenshot and locate the scroll, and program the mouse to click on a certain position on the scroll bar, but Mathematica alone cannot do this.

To get the scroll position using a mouse, you could use a Dynamic[MousePosition[]] while hovering over the scroll. You could set the position by dragging the scroll until the Dynamic[MousePosition[]] shows the coordinate you want.

While Mathematica alone cannot programmatically set the scroll position directly, it is possible to do so indirectly using functions accepting AutoScroll->True, e.g. NotebookFind or NotebookLocate mentioned in the question's comments. However, such functions will have the side effect of modifying the current selection.

You may be able to achieve the functionality you want by moving the current selection with AutoScroll. A coarse solution moves the selection to a cell:

cell[nb_, cell_, scroll_] := SelectionMove[Cells[nb][[cell]], All, Cell, AutoScroll -> scroll]

A finer solution moves the selection among characters within a cell:

char[nb_, n_, scroll_] := (SelectionMove[nb, After, CellContents, AutoScroll -> scroll];
                           SelectionMove[nb, Previous, Character, n, AutoScroll -> scroll])

Getting the selection position is trickier. To get the selected cell:

cell[nb_, scroll_] := 
    (If[0 == Length[SelectedCells[nb]], SelectionMove[nb, Next, Cell, AutoScroll -> scroll];
     If[0 == Length[SelectedCells[nb]], SelectionMove[nb, Previous, Cell, AutoScroll -> scroll];]];
     FirstPosition[Cells[nb], SelectedCells[nb][[1]]][[1]])

The If clauses are for handling cases where the selection is in between cells. Finer precision requires first counting the number of characters needed to move the selection to the end of the cell:

char[nb_, scroll_] := Module[{char = 0}, 
 For[SelectionMove[nb, All, Character, AutoScroll -> scroll], {} =!= NotebookRead[nb], 
     SelectionMove[nb, All, Character, AutoScroll -> scroll],
     SelectionMove[nb, Next, Character, AutoScroll -> scroll];
     ++char];
 char]

This function is slow. I tried to move the selection with units coarser than Character, e.g. Word, Expression and TextLine, but found the selection would sometimes get stuck in position.

Using these functions, it should have been possible to reset the selection to its original position after auto-scrolling to the desired position:

scroll[nchar_, ncell_] := Module[{ochar = char[original, False], ocell = cell[original, False]},
       cell[original, ncell, True];
       char[original, nchar, True];
       cell[original, ocell, False];
     (*char[original, ochar, False];*) (* auto scrolls anyway *)]

However, SelectionMove across Character units seems to ignore AutoScroll->False, and auto scrolls to the original position anyway. Therefore, the new scroll position can only be maintained if the selection is only returned to its original cell, and not its original position within the cell.

This method is limited in resolution by character widths and line heights, and may be unable to handle cells with graphics, but may be sufficient for some purposes.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.