src/Tools/Graphview/popups.scala
author wenzelm
Fri, 01 Apr 2022 17:06:10 +0200
changeset 75393 87ebf5a50283
parent 59459 985fc55e9f27
child 75418 6e0a452dab72
permissions -rw-r--r--
clarified formatting, for the sake of scala3;

/*  Title:      Tools/Graphview/popups.scala
    Author:     Markus Kaiser, TU Muenchen
    Author:     Makarius

PopupMenu generation for graph components.
*/

package isabelle.graphview


import isabelle._

import javax.swing.JPopupMenu
import scala.swing.{Action, Menu, MenuItem, Separator}


object Popups {
  def apply(
    graph_panel: Graph_Panel,
    mouse_node: Option[Graph_Display.Node],
    selected_nodes: List[Graph_Display.Node]
  ): JPopupMenu = {
    val graphview = graph_panel.graphview

    val add_mutator = graphview.model.Mutators.add _
    val visible_graph = graphview.visible_graph

    def filter_context(
        nodes: List[Graph_Display.Node], reverse: Boolean, caption: String, edges: Boolean) =
      new Menu(caption) {
        contents +=
          new MenuItem(new Action("This") {
            def apply =
              add_mutator(Mutator.make(graphview, Mutator.Node_List(nodes, reverse, false, false)))
          })

        contents +=
          new MenuItem(new Action("Family") {
            def apply =
              add_mutator(Mutator.make(graphview, Mutator.Node_List(nodes, reverse, true, true)))
          })

        contents +=
          new MenuItem(new Action("Parents") {
            def apply =
              add_mutator(Mutator.make(graphview, Mutator.Node_List(nodes, reverse, false, true)))
          })

        contents +=
          new MenuItem(new Action("Children") {
            def apply =
              add_mutator(Mutator.make(graphview, Mutator.Node_List(nodes, reverse, true, false)))
          })

        if (edges) {
          def degree_nodes(succs: Boolean) =
            (for {
              from <- nodes.iterator
              tos = if (succs) visible_graph.imm_succs(from) else visible_graph.imm_preds(from)
              if tos.nonEmpty
            } yield (from, tos)).toList.sortBy(_._1)(Graph_Display.Node.Ordering)

          val outs = degree_nodes(true)
          val ins = degree_nodes(false)

          if (outs.nonEmpty || ins.nonEmpty) {
            contents += new Separator()
            contents +=
              new Menu("Edge") {
                if (outs.nonEmpty) {
                  contents += new MenuItem("From ...") { enabled = false }
                  for ((from, tos) <- outs) {
                    contents +=
                      new Menu(quote(from.toString)) {
                        contents += new MenuItem("To ...") { enabled = false }
                        for (to <- tos) {
                          contents +=
                            new MenuItem(
                              new Action(quote(to.toString)) {
                                def apply =
                                  add_mutator(
                                    Mutator.make(graphview, Mutator.Edge_Endpoints((from, to))))
                              })
                        }
                      }
                  }
                }
                if (outs.nonEmpty && ins.nonEmpty) { contents += new Separator() }
                if (ins.nonEmpty) {
                  contents += new MenuItem("To ...") { enabled = false }
                  for ((to, froms) <- ins) {
                    contents +=
                      new Menu(quote(to.toString)) {
                        contents += new MenuItem("From ...") { enabled = false }
                        for (from <- froms) {
                          contents +=
                            new MenuItem(
                              new Action(quote(from.toString)) {
                                def apply =
                                  add_mutator(
                                    Mutator.make(graphview, Mutator.Edge_Endpoints((from, to))))
                              })
                        }
                      }
                  }
                }
              }
          }
        }
    }

    val popup = new JPopupMenu()

    popup.add(
      new MenuItem(
        new Action("Remove all filters") { def apply = graphview.model.Mutators(Nil) }).peer)
    popup.add(new JPopupMenu.Separator)

    if (mouse_node.isDefined) {
      val node = mouse_node.get
      popup.add(new MenuItem("Mouse over: " + quote(node.toString)) { enabled = false }.peer)

      popup.add(filter_context(List(node), true, "Hide", true).peer)
      popup.add(filter_context(List(node), false, "Show only", false).peer)

      popup.add(new JPopupMenu.Separator)
    }
    if (selected_nodes.nonEmpty) {
      val text =
        if (selected_nodes.length > 1) "multiple"
        else quote(selected_nodes.head.toString)

      popup.add(new MenuItem("Selected: " + text) { enabled = false }.peer)

      popup.add(filter_context(selected_nodes, true, "Hide", true).peer)
      popup.add(filter_context(selected_nodes, false, "Show only", false).peer)
      popup.add(new JPopupMenu.Separator)
    }

    popup.add(new MenuItem(new Action("Fit to window") {
      def apply = graph_panel.fit_to_window() }).peer
    )

    popup
  }
}