src/Tools/jEdit/src/pretty_tooltip.scala
author wenzelm
Fri, 05 Oct 2012 14:32:56 +0200
changeset 49712 a1bd8fe5131b
parent 49710 21d88a631fcc
child 49725 f8eeff667076
permissions -rw-r--r--
further support for nested tooltips;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
49702
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
     1
/*  Title:      Tools/jEdit/src/pretty_tooltip.scala
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
     3
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
     4
Enhanced tooltip window based on Pretty_Text_Area.
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
     5
*/
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
     6
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
     7
package isabelle.jedit
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
     8
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
     9
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    10
import isabelle._
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    11
49712
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    12
import java.awt.{Toolkit, Color, Point, BorderLayout, Window}
49705
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    13
import java.awt.event.{ActionListener, ActionEvent, KeyEvent, WindowEvent, WindowAdapter}
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    14
import javax.swing.{SwingUtilities, JWindow, JPanel, JComponent, KeyStroke}
49702
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    15
import javax.swing.border.LineBorder
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    16
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    17
import org.gjt.sp.jedit.View
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    18
import org.gjt.sp.jedit.textarea.TextArea
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    19
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    20
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    21
class Pretty_Tooltip(
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    22
  view: View,
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    23
  text_area: TextArea,
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    24
  rendering: Isabelle_Rendering,
49710
21d88a631fcc refer to parent frame -- relevant for floating dockables in particular;
wenzelm
parents: 49709
diff changeset
    25
  mouse_x: Int, mouse_y: Int, body: XML.Body)
49712
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    26
  extends JWindow(JEdit_Lib.parent_window(text_area) getOrElse view)
49702
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    27
{
49705
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    28
  window =>
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    29
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    30
  window.addWindowFocusListener(new WindowAdapter {
49712
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    31
    override def windowLostFocus(e: WindowEvent) {
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    32
      if (!Window.getWindows.exists(w =>
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    33
            w.isDisplayable && JEdit_Lib.ancestors(w).exists(_ == window)))
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    34
        window.dispose()
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    35
    }
49702
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    36
  })
49705
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    37
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    38
  window.setContentPane(new JPanel(new BorderLayout) {
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    39
    private val action_listener = new ActionListener {
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    40
      def actionPerformed(e: ActionEvent) {
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    41
        e.getActionCommand match {
49712
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    42
          case "close" =>
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    43
            window.dispose()
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    44
            JEdit_Lib.ancestors(window) foreach {
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    45
              case c: Pretty_Tooltip => c.dispose
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    46
              case _ =>
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    47
            }
49705
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    48
          case _ =>
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    49
        }
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    50
      }
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    51
    }
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    52
    registerKeyboardAction(action_listener, "close",
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    53
      KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_FOCUSED)
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    54
49702
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    55
    override def getFocusTraversalKeysEnabled(): Boolean = false
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    56
  })
49705
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    57
  window.getRootPane.setBorder(new LineBorder(Color.BLACK))
49702
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    58
49703
c89fffb11769 some re-ordering of initialization to ensure proper formatting;
wenzelm
parents: 49702
diff changeset
    59
  val pretty_text_area = new Pretty_Text_Area(view)
49706
92ef8b638c6c tuned color and font size;
wenzelm
parents: 49705
diff changeset
    60
  pretty_text_area.getPainter.setBackground(rendering.tooltip_color)
49703
c89fffb11769 some re-ordering of initialization to ensure proper formatting;
wenzelm
parents: 49702
diff changeset
    61
  pretty_text_area.resize(
c89fffb11769 some re-ordering of initialization to ensure proper formatting;
wenzelm
parents: 49702
diff changeset
    62
    Isabelle.font_family(), Isabelle.font_size("jedit_tooltip_font_scale").round)
c89fffb11769 some re-ordering of initialization to ensure proper formatting;
wenzelm
parents: 49702
diff changeset
    63
  pretty_text_area.update(rendering.snapshot, body)
c89fffb11769 some re-ordering of initialization to ensure proper formatting;
wenzelm
parents: 49702
diff changeset
    64
49706
92ef8b638c6c tuned color and font size;
wenzelm
parents: 49705
diff changeset
    65
  window.add(pretty_text_area)
49708
295ec55e7baa tuned window position;
wenzelm
parents: 49707
diff changeset
    66
295ec55e7baa tuned window position;
wenzelm
parents: 49707
diff changeset
    67
  {
49707
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
    68
    val font_metrics = pretty_text_area.getPainter.getFontMetrics
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
    69
    val margin = Isabelle.options.int("jedit_tooltip_margin")  // FIXME via rendering?!
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
    70
    val lines =  // FIXME avoid redundant formatting
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
    71
      XML.traverse_text(Pretty.formatted(body, margin, Pretty.font_metric(font_metrics)))(0)(
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
    72
        (n: Int, s: String) => n + s.iterator.filter(_ == '\n').length)
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
    73
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
    74
    val screen = Toolkit.getDefaultToolkit.getScreenSize
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
    75
    val w = (font_metrics.charWidth(Pretty.spc) * margin) min (screen.width / 2)
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
    76
    val h = (font_metrics.getHeight * (lines + 2)) min (screen.height / 2)
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
    77
    window.setSize(w, h)
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
    78
  }
49706
92ef8b638c6c tuned color and font size;
wenzelm
parents: 49705
diff changeset
    79
49709
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
    80
  {
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
    81
    val container = text_area.getPainter
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
    82
    val font_metrics = container.getFontMetrics
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
    83
    val point = new Point(mouse_x, mouse_y + font_metrics.getHeight / 2)
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
    84
    SwingUtilities.convertPointToScreen(point, container)
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
    85
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
    86
    val screen = Toolkit.getDefaultToolkit.getScreenSize
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
    87
    val x = point.x min (screen.width - window.getWidth)
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
    88
    val y = point.y min (screen.height - window.getHeight)
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
    89
    window.setLocation(x, y)
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
    90
  }
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
    91
49705
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    92
  window.setVisible(true)
49707
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
    93
  pretty_text_area.refresh()  // FIXME avoid redundant formatting
49702
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    94
}
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    95