How to create tabbed Mathematica notebooks
Asked Answered
W

1

21

Is there a way to create and edit notebooks (sequences of cells) in a tabbed interface? Could such an interface be made with TabView or some other tool? I assume this would be possible if I made a front-end from scratch, but is there a way within the standard Wolfram front-end?


Two things motivate me to ask this. First, I would like to create a replacement for Microsoft Office OneNote with Mathematica notebooks. Second, when I'm working in Mathematica I find myself wondering whether a tabbed interface would work better than having numerous separate windows open.

Whetstone answered 8/1, 2012 at 15:33 Comment(9)
Mathematica supports pagination of notebooks for presentations, and it also supports "docked cells" (always shown at the top). You may be able to combine the two to create a user interface in the docked cell for switching between the pages. This is just an idea for a starting point.Amphigory
I posted an answer that after thinking more about it only works for output. I think the quickest to do this would be to create a separate tab bar or palette that switches between windows by setting Visible->False for all but the selected window/notebook. This may give the illusion of a tabbed interface.Cowpoke
There is no built-in (native) tabbed interface in the Mathematica frontend user interface (but this is an excellent suggestion to report to [email protected]). The nearest thing in the frontend user interface that I can think of, is the slide show environment (open the Palettes menu and select Slide Show).Deforce
@Mike Here's a starting point, but I expect this to get very messy ... PaletteNotebook@ DynamicModule[{nb}, Dynamic[nb = SelectedNotebook[]; SetterBar[Dynamic[nb, (SetSelectedNotebook[#]) &], SortBy[Thread[ Notebooks[] -> NotebookTools`NotebookName /@ Notebooks[]], Last]]]]Amphigory
Nice one @Amphigory ! Where did you learn about the NotebookTools context?Cowpoke
@Mike I don't remember ... maybe I did ?*`Notebook* or something like that. Much of it is identical to the (documented) AuthorTools package, see https://mcmap.net/q/661266/-steps-to-compare-notebooks-in-workbench/695132Amphigory
Ah! I did ?NotebookTools'* and thought some of the functions looked familiar. I used to use AuthorTools a lot many years ago.Cowpoke
@Amphigory I did ?*`Notebook* and found your gold mine -- but I'm having trouble actually getting to the namespaces: NotebookTools` shows up in the result of ?*`Notebook*, but Needs["NotebookTools`"] produces Needs::nocont: Context NotebookTools\ was not created when Needs was evaluated.` so it's hiding somewhere. Ditto Get... Clues?Executrix
@Executrix There's no need to load anything, the symbols are already there. You just need to use NotebookTools`NotebookName[] and not NotebookName[]. You can read about contexts here. Of course you can add NotebookTools` to $ContextPath if you really wish. But please keep in mind that all this in undocumented functionality so there's no telling what going to happen to it in the next version, or even if it works without messing anything up in the current version (I burnt myself with other functions before ...)Amphigory
T
10

While Mathematica doesn't support tabbed notebook windows directly, it is possible to reproduce something of the effect using DockedCells. The Virtual Book/Function Navigator interface (from the help menu) does this...it's essentially a slide show with two slides, one holding the VB and the other containing the FN, with a DockedCells navigation interface driven by NotebookFind that looks a bit like tabs.

Here's the gist of how you might go about making such a notebook on your own. Sorry, there are some kind of advanced concepts here...if there's any parts of this solution which you want to learn more about, maybe you can spin off more questions.

(* make a single page of the notebook *)
page[tag_String] := 
  Cell@CellGroupData[{Cell["", "SlideShowNavigationBar", 
      CellTags -> {tag}], Cell[tag, "Title"]}];
(* make a single tab-like button which selects the page *)
button[tag_String] := 
  Button[Dynamic[
    Setter[Dynamic[
      CurrentValue[EvaluationNotebook[], {TaggingRules, "page"}, 
       tag]], tag]], 
   CurrentValue[EvaluationNotebook[], {TaggingRules, "page"}] = tag; 
   NotebookLocate[tag], 
   Appearance -> None];
(* make a notebook based upon a list of strings which are names of tabs *)
makeTabbedNotebook[nameList_List] :=
  NotebookPut@Notebook[page /@ nameList,
    DockedCells -> 
     ToBoxes[ExpressionCell[Row[button /@ nameList], 
        "DockedCell"]][[1]], 
    ScreenStyleEnvironment -> "SlideShow"];

makeTabbedNotebook[{"First", "Second", "Third"}]

Edit: changed NotebookFind[ButtonNotebook[],tag,All,CellTags], which appears to not always scroll the slideshow correctly, to NotebookLocate[tag]. See discussion in comments. The two bits of code should, in theory, be equivalent, but a bug in Mathematica 8 appears to make them behave differently sometimes.

Tailpiece answered 16/1, 2012 at 22:3 Comment(8)
John, I noticed on V 8.04, when I run the above, and it is now setting at 'First', then I click on 'Second', then the button shows it is now on 'second' but the page displays 'First'. But when I am on 'third' and click on 'second, then it does change ok. I am sure this is easy to fix, but your code is too advanced for me to figure it out now :). I can add screen shot, but do not know how to do it in comment.Cerys
Replacing the line NotebookFind[ButtonNotebook[],tag,All,CellTags] with NotebookLocate[tag] seems to correct the issue in @Nasser's comment. Also, there is an extra term tag inside Setter[Dynamic[CurrentValue[....] ... that needs be deleted.Materialism
@kguler I think you mean tag inside CurrentValue, not in Setter. If you remove this, the Setter won't appear pressed until you actually press a button. It appears to be an undocumented third argument that provides a default value.Amphigory
@Szabolcs, yes, I mean the first of two consecutive tags which gets highlighted as red by syntax highlighter. However, it works both with and without the first of the two consecutive tags. It is very unlikely to be a typo.Materialism
@kguler To clarify, in my previous comment I meant that the red tag is necessary for this to work correctly. Without it no setter will appear pressed initially, as the notebook is created. It should not be removed.Amphigory
@Szabolc, I agree, it is setting the first argument of Setter to tag which is needed for the setter to look pressed.Materialism
@Nasser, seems to be a bug in the FE. I've confirmed that NotebookFind is finding the correct cell, but the FE is just not properly scrolling in this case. I'll look into it. In the mean time, I'll change my answer above to use NotebookLocate, which is nicely advantageous because it's simpler anyway.Tailpiece
@Szabolcs, the third (undocumented) argument to CurrentValue will create and set the value if the value doesn't exist. It's a very convenient way to establish default values of CurrentValue selectors (of the sort documented in the TaggingRules documentation) without writing a bunch of messy code.Tailpiece

© 2022 - 2024 — McMap. All rights reserved.