src/Tools/jEdit/src/pretty_tooltip.scala
author wenzelm
Fri, 14 Dec 2012 21:26:01 +0100
changeset 50538 48cb76b785da
parent 50501 6f41f1646617
child 50554 0493efcc97e9
permissions -rw-r--r--
init gutter according to view properties, which improves symmetry of windows and allows use of folds etc;
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
50167
4f2b5b2a9ad5 more precise tooltip window size;
wenzelm
parents: 50146
diff changeset
    12
import java.awt.{Toolkit, Color, Point, BorderLayout, Window, Dimension}
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
49725
f8eeff667076 explicit close button;
wenzelm
parents: 49712
diff changeset
    17
import scala.swing.{FlowPanel, Label}
f8eeff667076 explicit close button;
wenzelm
parents: 49712
diff changeset
    18
import scala.swing.event.MouseClicked
f8eeff667076 explicit close button;
wenzelm
parents: 49712
diff changeset
    19
49702
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    20
import org.gjt.sp.jedit.View
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    21
import org.gjt.sp.jedit.textarea.TextArea
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    22
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    23
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    24
class Pretty_Tooltip(
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    25
  view: View,
49730
e0d98ff3c0db use Pretty_Tooltip for Graphview_Panel;
wenzelm
parents: 49728
diff changeset
    26
  parent: JComponent,
50199
6d04e2422769 quasi-abstract module Rendering, with Isabelle-specific implementation;
wenzelm
parents: 50169
diff changeset
    27
  rendering: Rendering,
50501
6f41f1646617 more careful handling of Dialog_Result, with active area and color feedback;
wenzelm
parents: 50206
diff changeset
    28
  mouse_x: Int, mouse_y: Int,
6f41f1646617 more careful handling of Dialog_Result, with active area and color feedback;
wenzelm
parents: 50206
diff changeset
    29
  results: Command.Results,
6f41f1646617 more careful handling of Dialog_Result, with active area and color feedback;
wenzelm
parents: 50206
diff changeset
    30
  body: XML.Body)
49730
e0d98ff3c0db use Pretty_Tooltip for Graphview_Panel;
wenzelm
parents: 49728
diff changeset
    31
  extends JWindow(JEdit_Lib.parent_window(parent) getOrElse view)
49702
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    32
{
49705
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    33
  window =>
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    34
49725
f8eeff667076 explicit close button;
wenzelm
parents: 49712
diff changeset
    35
  Swing_Thread.require()
f8eeff667076 explicit close button;
wenzelm
parents: 49712
diff changeset
    36
f8eeff667076 explicit close button;
wenzelm
parents: 49712
diff changeset
    37
49705
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    38
  window.addWindowFocusListener(new WindowAdapter {
49712
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    39
    override def windowLostFocus(e: WindowEvent) {
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    40
      if (!Window.getWindows.exists(w =>
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    41
            w.isDisplayable && JEdit_Lib.ancestors(w).exists(_ == window)))
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    42
        window.dispose()
a1bd8fe5131b further support for nested tooltips;
wenzelm
parents: 49710
diff changeset
    43
    }
49702
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    44
  })
49705
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    45
49728
74f36dab2b62 close tooltips more thoroughly;
wenzelm
parents: 49727
diff changeset
    46
  private val action_listener = new ActionListener {
74f36dab2b62 close tooltips more thoroughly;
wenzelm
parents: 49727
diff changeset
    47
    def actionPerformed(e: ActionEvent) {
74f36dab2b62 close tooltips more thoroughly;
wenzelm
parents: 49727
diff changeset
    48
      e.getActionCommand match {
74f36dab2b62 close tooltips more thoroughly;
wenzelm
parents: 49727
diff changeset
    49
        case "close_all" =>
74f36dab2b62 close tooltips more thoroughly;
wenzelm
parents: 49727
diff changeset
    50
          Window.getWindows foreach {
74f36dab2b62 close tooltips more thoroughly;
wenzelm
parents: 49727
diff changeset
    51
            case c: Pretty_Tooltip => c.dispose
74f36dab2b62 close tooltips more thoroughly;
wenzelm
parents: 49727
diff changeset
    52
            case _ =>
74f36dab2b62 close tooltips more thoroughly;
wenzelm
parents: 49727
diff changeset
    53
          }
74f36dab2b62 close tooltips more thoroughly;
wenzelm
parents: 49727
diff changeset
    54
        case _ =>
49705
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    55
      }
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    56
    }
49728
74f36dab2b62 close tooltips more thoroughly;
wenzelm
parents: 49727
diff changeset
    57
  }
74f36dab2b62 close tooltips more thoroughly;
wenzelm
parents: 49727
diff changeset
    58
74f36dab2b62 close tooltips more thoroughly;
wenzelm
parents: 49727
diff changeset
    59
  window.setContentPane(new JPanel(new BorderLayout) {
49842
a974f66062c8 more uniform tooltip color;
wenzelm
parents: 49730
diff changeset
    60
    setBackground(rendering.tooltip_color)
49728
74f36dab2b62 close tooltips more thoroughly;
wenzelm
parents: 49727
diff changeset
    61
    registerKeyboardAction(action_listener, "close_all",
49705
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    62
      KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_FOCUSED)
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    63
49702
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    64
    override def getFocusTraversalKeysEnabled(): Boolean = false
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    65
  })
49705
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
    66
  window.getRootPane.setBorder(new LineBorder(Color.BLACK))
49702
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
    67
49725
f8eeff667076 explicit close button;
wenzelm
parents: 49712
diff changeset
    68
f8eeff667076 explicit close button;
wenzelm
parents: 49712
diff changeset
    69
  /* pretty text area */
f8eeff667076 explicit close button;
wenzelm
parents: 49712
diff changeset
    70
50538
48cb76b785da init gutter according to view properties, which improves symmetry of windows and allows use of folds etc;
wenzelm
parents: 50501
diff changeset
    71
  val pretty_text_area = new Pretty_Text_Area(view, Some(rendering.tooltip_color))
50206
6626bc5ed053 tuned signature;
wenzelm
parents: 50205
diff changeset
    72
  pretty_text_area.resize(Rendering.font_family(),
6626bc5ed053 tuned signature;
wenzelm
parents: 50205
diff changeset
    73
    Rendering.font_size("jedit_tooltip_font_scale").round)
50501
6f41f1646617 more careful handling of Dialog_Result, with active area and color feedback;
wenzelm
parents: 50206
diff changeset
    74
  pretty_text_area.update(rendering.snapshot, results, body)
49703
c89fffb11769 some re-ordering of initialization to ensure proper formatting;
wenzelm
parents: 49702
diff changeset
    75
49728
74f36dab2b62 close tooltips more thoroughly;
wenzelm
parents: 49727
diff changeset
    76
  pretty_text_area.registerKeyboardAction(action_listener, "close_all",
50167
4f2b5b2a9ad5 more precise tooltip window size;
wenzelm
parents: 50146
diff changeset
    77
    KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_FOCUSED)
49728
74f36dab2b62 close tooltips more thoroughly;
wenzelm
parents: 49727
diff changeset
    78
49706
92ef8b638c6c tuned color and font size;
wenzelm
parents: 49705
diff changeset
    79
  window.add(pretty_text_area)
49708
295ec55e7baa tuned window position;
wenzelm
parents: 49707
diff changeset
    80
49725
f8eeff667076 explicit close button;
wenzelm
parents: 49712
diff changeset
    81
f8eeff667076 explicit close button;
wenzelm
parents: 49712
diff changeset
    82
  /* controls */
f8eeff667076 explicit close button;
wenzelm
parents: 49712
diff changeset
    83
49727
2fe56b600698 make buttons closer to original mouse position;
wenzelm
parents: 49726
diff changeset
    84
  private val close = new Label {
50199
6d04e2422769 quasi-abstract module Rendering, with Isabelle-specific implementation;
wenzelm
parents: 50169
diff changeset
    85
    icon = Rendering.tooltip_close_icon
49727
2fe56b600698 make buttons closer to original mouse position;
wenzelm
parents: 49726
diff changeset
    86
    tooltip = "Close tooltip window"
2fe56b600698 make buttons closer to original mouse position;
wenzelm
parents: 49726
diff changeset
    87
    listenTo(mouse.clicks)
2fe56b600698 make buttons closer to original mouse position;
wenzelm
parents: 49726
diff changeset
    88
    reactions += { case _: MouseClicked => window.dispose() }
2fe56b600698 make buttons closer to original mouse position;
wenzelm
parents: 49726
diff changeset
    89
  }
2fe56b600698 make buttons closer to original mouse position;
wenzelm
parents: 49726
diff changeset
    90
49726
2074197dc274 detach tooltip as dockable window;
wenzelm
parents: 49725
diff changeset
    91
  private val detach = new Label {
50199
6d04e2422769 quasi-abstract module Rendering, with Isabelle-specific implementation;
wenzelm
parents: 50169
diff changeset
    92
    icon = Rendering.tooltip_detach_icon
49726
2074197dc274 detach tooltip as dockable window;
wenzelm
parents: 49725
diff changeset
    93
    tooltip = "Detach tooltip window"
2074197dc274 detach tooltip as dockable window;
wenzelm
parents: 49725
diff changeset
    94
    listenTo(mouse.clicks)
2074197dc274 detach tooltip as dockable window;
wenzelm
parents: 49725
diff changeset
    95
    reactions += {
50501
6f41f1646617 more careful handling of Dialog_Result, with active area and color feedback;
wenzelm
parents: 50206
diff changeset
    96
      case _: MouseClicked =>
6f41f1646617 more careful handling of Dialog_Result, with active area and color feedback;
wenzelm
parents: 50206
diff changeset
    97
        Info_Dockable(view, rendering.snapshot, results, body)
6f41f1646617 more careful handling of Dialog_Result, with active area and color feedback;
wenzelm
parents: 50206
diff changeset
    98
        window.dispose()
49726
2074197dc274 detach tooltip as dockable window;
wenzelm
parents: 49725
diff changeset
    99
    }
2074197dc274 detach tooltip as dockable window;
wenzelm
parents: 49725
diff changeset
   100
  }
2074197dc274 detach tooltip as dockable window;
wenzelm
parents: 49725
diff changeset
   101
49842
a974f66062c8 more uniform tooltip color;
wenzelm
parents: 49730
diff changeset
   102
  private val controls = new FlowPanel(FlowPanel.Alignment.Left)(close, detach) {
a974f66062c8 more uniform tooltip color;
wenzelm
parents: 49730
diff changeset
   103
    background = rendering.tooltip_color
a974f66062c8 more uniform tooltip color;
wenzelm
parents: 49730
diff changeset
   104
  }
49725
f8eeff667076 explicit close button;
wenzelm
parents: 49712
diff changeset
   105
  window.add(controls.peer, BorderLayout.NORTH)
f8eeff667076 explicit close button;
wenzelm
parents: 49712
diff changeset
   106
f8eeff667076 explicit close button;
wenzelm
parents: 49712
diff changeset
   107
f8eeff667076 explicit close button;
wenzelm
parents: 49712
diff changeset
   108
  /* window geometry */
f8eeff667076 explicit close button;
wenzelm
parents: 49712
diff changeset
   109
49708
295ec55e7baa tuned window position;
wenzelm
parents: 49707
diff changeset
   110
  {
49707
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
   111
    val font_metrics = pretty_text_area.getPainter.getFontMetrics
50205
788c8263e634 renamed main plugin object to PIDE;
wenzelm
parents: 50199
diff changeset
   112
    val margin = PIDE.options.int("jedit_tooltip_margin")  // FIXME via rendering?!
50167
4f2b5b2a9ad5 more precise tooltip window size;
wenzelm
parents: 50146
diff changeset
   113
    val lines =
49707
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
   114
      XML.traverse_text(Pretty.formatted(body, margin, Pretty.font_metric(font_metrics)))(0)(
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
   115
        (n: Int, s: String) => n + s.iterator.filter(_ == '\n').length)
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
   116
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
   117
    val screen = Toolkit.getDefaultToolkit.getScreenSize
50167
4f2b5b2a9ad5 more precise tooltip window size;
wenzelm
parents: 50146
diff changeset
   118
    val w = (font_metrics.charWidth(Pretty.spc) * (margin + 2)) min (screen.width / 2)
4f2b5b2a9ad5 more precise tooltip window size;
wenzelm
parents: 50146
diff changeset
   119
    val h = (font_metrics.getHeight * (lines + 2)) min (screen.height / 2)
4f2b5b2a9ad5 more precise tooltip window size;
wenzelm
parents: 50146
diff changeset
   120
    pretty_text_area.setPreferredSize(new Dimension(w, h))
50169
071902349e3e pack window before accessing its geometry;
wenzelm
parents: 50167
diff changeset
   121
    window.pack
49707
e42f60561aa4 determine window size from content;
wenzelm
parents: 49706
diff changeset
   122
  }
49706
92ef8b638c6c tuned color and font size;
wenzelm
parents: 49705
diff changeset
   123
49709
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
   124
  {
49730
e0d98ff3c0db use Pretty_Tooltip for Graphview_Panel;
wenzelm
parents: 49728
diff changeset
   125
    val point = new Point(mouse_x, mouse_y)
e0d98ff3c0db use Pretty_Tooltip for Graphview_Panel;
wenzelm
parents: 49728
diff changeset
   126
    SwingUtilities.convertPointToScreen(point, parent)
49709
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
   127
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
   128
    val screen = Toolkit.getDefaultToolkit.getScreenSize
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
   129
    val x = point.x min (screen.width - window.getWidth)
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
   130
    val y = point.y min (screen.height - window.getHeight)
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
   131
    window.setLocation(x, y)
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
   132
  }
3062937b45b3 tuned window position to fit on screen;
wenzelm
parents: 49708
diff changeset
   133
49705
036c9a028dbd close tooltip window on escape;
wenzelm
parents: 49703
diff changeset
   134
  window.setVisible(true)
50167
4f2b5b2a9ad5 more precise tooltip window size;
wenzelm
parents: 50146
diff changeset
   135
  pretty_text_area.refresh()
49702
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
   136
}
696e91c0bc80 separate module Pretty_Tooltip;
wenzelm
parents:
diff changeset
   137