summaryrefslogtreecommitdiff
path: root/src/swing/scala/swing/RichWindow.scala
blob: 5cb6dfdf3339863c9b0d51d1018078bf2d4461e0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2007-2011, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */



package scala.swing

import java.awt.{Window => AWTWindow, Frame => AWTFrame}
import javax.swing._
import Swing._

object RichWindow {
  /**
   * Mixin this trait if you want an undecorated window.
   */
  trait Undecorated extends RichWindow {
    // we do a mixin here, since setUndecorated is only allowed to be called
    // when the component is not displayable.
    peer.setUndecorated(true)
  }
}

/**
 * A window that adds some functionality to the plain Window class and serves as
 * the common base class for frames and dialogs.
 *
 * Implementation note: this class is sealed since we need to know that a rich
 * window is either a dialog or a frame at some point.
 */
sealed trait RichWindow extends Window {
  def peer: AWTWindow with InterfaceMixin

  trait InterfaceMixin extends super.InterfaceMixin {
    def getJMenuBar: JMenuBar
    def setJMenuBar(b: JMenuBar)
    def setUndecorated(b: Boolean)
    def setTitle(s: String)
    def getTitle: String
    def setResizable(b: Boolean)
    def isResizable: Boolean
  }

  def title: String = peer.getTitle
  def title_=(s: String) = peer.setTitle(s)

  /**
   * The menu bar of this frame or `NoMenuBar` if no menu bar is set.
   */
  def menuBar: MenuBar = {
      val m = UIElement.cachedWrapper[MenuBar](peer.getJMenuBar)
      if (m != null) m else MenuBar.NoMenuBar
  }
  /**
   * Set the current menu bar of this frame. Pass `NoMenuBar` if this frame
   * should not show a menu bar.
   */
  def menuBar_=(m: MenuBar) =
    peer.setJMenuBar(if(m == MenuBar.NoMenuBar) null else m.peer)

  def resizable_=(b: Boolean) { peer.setResizable(b) }
  def resizable = peer.isResizable
}

/**
 * A window with decoration such as a title, border, and action buttons.
 *
 * An AWT window cannot be wrapped dynamically with this class, i.e., you cannot
 * write something like new Window { def peer = myAWTWindow }
 *
 * @see javax.swing.JFrame
 */
class Frame extends RichWindow {
  override lazy val peer: JFrame with InterfaceMixin = new JFrame with InterfaceMixin with SuperMixin

  protected trait SuperMixin extends JFrame {
    override protected def processWindowEvent(e: java.awt.event.WindowEvent) {
      super.processWindowEvent(e)
      if (e.getID() == java.awt.event.WindowEvent.WINDOW_CLOSING)
        closeOperation()
    }
  }

  def iconify() { peer.setExtendedState(peer.getExtendedState | AWTFrame.ICONIFIED) }
  def uniconify() { peer.setExtendedState(peer.getExtendedState & ~AWTFrame.ICONIFIED) }
  def iconified() { (peer.getExtendedState & AWTFrame.ICONIFIED) != 0 }
  def maximize() { peer.setExtendedState(peer.getExtendedState | AWTFrame.MAXIMIZED_BOTH) }
  def unmaximize() { peer.setExtendedState(peer.getExtendedState & ~AWTFrame.MAXIMIZED_BOTH) }
  def maximized() { (peer.getExtendedState & AWTFrame.MAXIMIZED_BOTH) != 0 }

  def iconImage: Image = peer.getIconImage
  def iconImage_=(i: Image) { peer.setIconImage(i) }
}

/**
 * Simple predefined dialogs.
 *
 * @see javax.swing.JOptionPane
 */
object Dialog {
  /**
   * The message type of a dialog.
   */
  object Message extends Enumeration {
    val Error = Value(JOptionPane.ERROR_MESSAGE)
    val Info = Value(JOptionPane.INFORMATION_MESSAGE)
    val Warning = Value(JOptionPane.WARNING_MESSAGE)
    val Question = Value(JOptionPane.QUESTION_MESSAGE)
    val Plain = Value(JOptionPane.PLAIN_MESSAGE)
  }

  /**
   * The possible answers a user can select.
   */
  object Options extends Enumeration {
    val Default = Value(JOptionPane.DEFAULT_OPTION)
    val YesNo = Value(JOptionPane.YES_NO_OPTION)
    val YesNoCancel = Value(JOptionPane.YES_NO_CANCEL_OPTION)
    val OkCancel = Value(JOptionPane.OK_CANCEL_OPTION)
  }

  /**
   * The selected result of dialog.
   */
  object Result extends Enumeration {
    val Yes = Value(JOptionPane.YES_OPTION)
    val Ok = Yes
    val No = Value(JOptionPane.NO_OPTION)
    val Cancel = Value(JOptionPane.CANCEL_OPTION)
    val Closed = Value(JOptionPane.CLOSED_OPTION)
  }

  private def uiString(txt: String) = UIManager.getString(txt)

  def showConfirmation(parent: Component = null,
                       message: Any,
                       title: String = uiString("OptionPane.titleText"),
                       optionType: Options.Value = Options.YesNo,
                       messageType: Message.Value = Message.Question,
                       icon: Icon = EmptyIcon): Result.Value =
     Result(JOptionPane.showConfirmDialog(nullPeer(parent), message, title,
                                   optionType.id, messageType.id, Swing.wrapIcon(icon)))

  def showOptions(parent: Component = null,
                  message: Any,
                  title: String = uiString("OptionPane.titleText"),
                  optionType: Options.Value = Options.YesNo,
                  messageType: Message.Value = Message.Question,
                  icon: Icon = EmptyIcon,
                  entries: Seq[Any],
                  initial: Int): Result.Value = {
    val r = JOptionPane.showOptionDialog(nullPeer(parent), message, title,
                                   optionType.id, messageType.id, Swing.wrapIcon(icon),
                                   entries map toAnyRef toArray, entries(initial))
    Result(r)
  }

  def showInput[A](parent: Component = null,
                   message: Any,
                   title: String = uiString("OptionPane.inputDialogTitle"),
                   messageType: Message.Value = Message.Question,
                   icon: Icon = EmptyIcon,
                   entries: Seq[A] = Nil,
                   initial: A): Option[A] = {
    val e = if (entries.isEmpty) null
            else entries map toAnyRef toArray
    val r = JOptionPane.showInputDialog(nullPeer(parent), message, title,
        messageType.id, Swing.wrapIcon(icon),
        e, initial)

    toOption[A](r)
  }
  def showMessage(parent: Component = null,
                  message: Any,
                  title: String = uiString("OptionPane.messageDialogTitle"),
                  messageType: Message.Value = Message.Info,
                  icon: Icon = EmptyIcon) {
     JOptionPane.showMessageDialog(nullPeer(parent), message, title,
                                   messageType.id, Swing.wrapIcon(icon))
  }
}

/**
 * A dialog window.
 *
 * @see javax.swing.JDialog
 */
class Dialog(owner: Window) extends RichWindow {
  override lazy val peer: JDialog with InterfaceMixin =
    if (owner == null) new JDialog with InterfaceMixin
    else owner match {
      case f: Frame => new JDialog(f.peer) with InterfaceMixin
      case d: Dialog => new JDialog(d.peer) with InterfaceMixin
    }

  def this() = this(null)

  def modal_=(b: Boolean) { peer.setModal(b) }
  def modal = peer.isModal
}