|
| 1 | +/* |
| 2 | + * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved. |
| 3 | + * |
| 4 | + * Redistribution and use in source and binary forms, with or without |
| 5 | + * modification, are permitted provided that the following conditions |
| 6 | + * are met: |
| 7 | + * |
| 8 | + * - Redistributions of source code must retain the above copyright |
| 9 | + * notice, this list of conditions and the following disclaimer. |
| 10 | + * |
| 11 | + * - Redistributions in binary form must reproduce the above copyright |
| 12 | + * notice, this list of conditions and the following disclaimer in the |
| 13 | + * documentation and/or other materials provided with the distribution. |
| 14 | + * |
| 15 | + * - Neither the name of Oracle or the names of its |
| 16 | + * contributors may be used to endorse or promote products derived |
| 17 | + * from this software without specific prior written permission. |
| 18 | + * |
| 19 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
| 20 | + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| 21 | + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 22 | + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| 23 | + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 24 | + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 25 | + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 26 | + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| 27 | + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 28 | + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 29 | + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 | + */ |
| 31 | +package scala.swing.examples.tutorials.components |
| 32 | + |
| 33 | +import scala.swing._ |
| 34 | +import scala.swing.event.ButtonClicked |
| 35 | +import javax.swing.{ Box, BoxLayout, JDialog, JFrame, ImageIcon, UIManager } |
| 36 | +import java.awt.{ BorderLayout, Color, Component, Dimension, Graphics, Image, Point, Toolkit } |
| 37 | +import java.awt.image.BufferedImage |
| 38 | +import java.net.URL |
| 39 | + |
| 40 | +/* |
| 41 | + * Tutorial: How to Make Frames (Main Windows) |
| 42 | + * http://docs.oracle.com/javase/tutorial/uiswing/components/frame.html |
| 43 | + * |
| 44 | + * Source code reference: |
| 45 | + * http://docs.oracle.com/javase/tutorial/uiswing/examples/components/FrameDemo2Project/src/components/FrameDemo2.java |
| 46 | + * |
| 47 | + * FrameDemo2.scala shows off the window decoration features added in |
| 48 | + * 1.4, plus some window positioning code and (optionally) |
| 49 | + * setIconImage. It uses the file /scala/swing/examples/tutorials/images/FD.jpg. |
| 50 | + */ |
| 51 | +class FrameDemo2 { |
| 52 | + private var lastLocation: Point = null |
| 53 | + private var defaultButton: Button = null |
| 54 | + // private val maxX = 500 |
| 55 | + // private val maxY = 500 |
| 56 | + //constants for action commands |
| 57 | + val NO_DECORATIONS = "no_dec"; |
| 58 | + val LF_DECORATIONS = "laf_dec"; |
| 59 | + val WS_DECORATIONS = "ws_dec"; |
| 60 | + val CREATE_WINDOW = "new_win"; |
| 61 | + val DEFAULT_ICON = "def_icon"; |
| 62 | + val FILE_ICON = "file_icon"; |
| 63 | + val PAINT_ICON = "paint_icon"; |
| 64 | + |
| 65 | + //true if the next frame created should have no window decorations |
| 66 | + var noDecorations = false; |
| 67 | + |
| 68 | + //true if the next frame created should have setIconImage called |
| 69 | + var specifyIcon = false; |
| 70 | + |
| 71 | + //true if the next frame created should have a custom painted icon |
| 72 | + var createIcon = false; |
| 73 | + |
| 74 | + val screenSize: Dimension = Toolkit.getDefaultToolkit().getScreenSize() |
| 75 | + val maxX = screenSize.width - 50 |
| 76 | + val maxY = screenSize.height - 50 |
| 77 | + |
| 78 | + //Create a new MyFrame object and show it. |
| 79 | + def showNewWindow(): Unit = { |
| 80 | + //Take care of the no window decorations case. |
| 81 | + //NOTE: Unless you really need the functionality |
| 82 | + //provided by JFrame, you would usually use a |
| 83 | + //Window or JWindow instead of an undecorated JFrame. |
| 84 | + val frame: Option[Frame] = if (noDecorations) Some(new MyFrameUndecorated()) else Some(new MyFrame()) |
| 85 | + //Set window location. |
| 86 | + if (frame.isDefined) { |
| 87 | + val f = frame.get |
| 88 | + if (lastLocation != null) { |
| 89 | + //Move the window over and down 40 pixels. |
| 90 | + lastLocation.translate(40, 40); |
| 91 | + if ((lastLocation.x > maxX) || (lastLocation.y > maxY)) { |
| 92 | + lastLocation.setLocation(0, 0); |
| 93 | + } |
| 94 | + f.location = lastLocation |
| 95 | + } else { |
| 96 | + lastLocation = f.location |
| 97 | + } |
| 98 | + |
| 99 | + //Calling setIconImage sets the icon displayed when the window |
| 100 | + //is minimized. Most window systems (or look and feels, if |
| 101 | + //decorations are provided by the look and feel) also use this |
| 102 | + //icon in the window decorations. |
| 103 | + if (specifyIcon) { |
| 104 | + if (createIcon) { |
| 105 | + //create an icon from scratch |
| 106 | + f.iconImage = FrameDemo2.createFDImage() |
| 107 | + } else { |
| 108 | + //get the icon from a file |
| 109 | + f.iconImage = FrameDemo2.getFDImage().get |
| 110 | + } |
| 111 | + } |
| 112 | + } |
| 113 | + } |
| 114 | + |
| 115 | + // Create the window-creation controls that go in the main window. |
| 116 | + def createOptionControls(frame: Frame): BoxPanel = { |
| 117 | + val label1 = new Label("Decoration options for subsequently created frames:") |
| 118 | + val bg1 = new ButtonGroup() |
| 119 | + val label2 = new Label("Icon options:") |
| 120 | + val bg2 = new ButtonGroup() |
| 121 | + |
| 122 | + //Create the buttons |
| 123 | + val rb1 = new RadioButton() { |
| 124 | + text = "Look and feel decorated" |
| 125 | + selected = true |
| 126 | + } |
| 127 | + bg1.buttons += rb1 |
| 128 | + // |
| 129 | + val rb2 = new RadioButton() { |
| 130 | + text = "Window system decorated" |
| 131 | + } |
| 132 | + bg1.buttons += rb2 |
| 133 | + // |
| 134 | + val rb3 = new RadioButton() { |
| 135 | + text = "No decorations" |
| 136 | + } |
| 137 | + bg1.buttons += rb3 |
| 138 | + // |
| 139 | + val rb4 = new RadioButton() { |
| 140 | + text = "Default icon" |
| 141 | + selected = true |
| 142 | + } |
| 143 | + bg2.buttons += rb4 |
| 144 | + // |
| 145 | + val rb5 = new RadioButton() { |
| 146 | + text = "Icon from a JPEG file" |
| 147 | + } |
| 148 | + bg2.buttons += rb5 |
| 149 | + // |
| 150 | + val rb6 = new RadioButton() { |
| 151 | + text = "Painted icon" |
| 152 | + } |
| 153 | + bg2.buttons += rb6 |
| 154 | + |
| 155 | + //Add everything to a container. |
| 156 | + val box = new BoxPanel(Orientation.Vertical) { |
| 157 | + border = Swing.EmptyBorder(10, 10, 10, 10) |
| 158 | + contents += label1 |
| 159 | + contents += Swing.VStrut(5) // spacer |
| 160 | + contents += rb1 |
| 161 | + contents += rb2 |
| 162 | + contents += rb3 |
| 163 | + contents += Swing.VStrut(15) |
| 164 | + contents += label2 |
| 165 | + contents += Swing.VStrut(5) |
| 166 | + contents += rb4 |
| 167 | + contents += rb5 |
| 168 | + contents += rb6 |
| 169 | + } |
| 170 | + |
| 171 | + frame.listenTo(rb1) |
| 172 | + frame.listenTo(rb2) |
| 173 | + frame.listenTo(rb3) |
| 174 | + frame.listenTo(rb4) |
| 175 | + frame.listenTo(rb5) |
| 176 | + frame.listenTo(rb6) |
| 177 | + frame.reactions += { |
| 178 | + case ButtonClicked(`rb1`) => |
| 179 | + noDecorations = false |
| 180 | + JFrame.setDefaultLookAndFeelDecorated(true) |
| 181 | + case ButtonClicked(`rb2`) => |
| 182 | + noDecorations = false |
| 183 | + JFrame.setDefaultLookAndFeelDecorated(false) |
| 184 | + case ButtonClicked(`rb3`) => |
| 185 | + noDecorations = true |
| 186 | + // No need to set the default look and feel decorated property to false. |
| 187 | + // JFrame.setDefaultLookAndFeelDecorated(false) |
| 188 | + case ButtonClicked(`rb4`) => specifyIcon = false |
| 189 | + case ButtonClicked(`rb5`) => |
| 190 | + specifyIcon = true |
| 191 | + createIcon = false |
| 192 | + case ButtonClicked(`rb6`) => |
| 193 | + specifyIcon = true |
| 194 | + createIcon = true |
| 195 | + } |
| 196 | + |
| 197 | + box |
| 198 | + } |
| 199 | + |
| 200 | + //Create the button that goes in the main window. |
| 201 | + def createButtonPane(frame: Frame): FlowPanel = { |
| 202 | + val button = new Button("New window") |
| 203 | + defaultButton = button |
| 204 | + |
| 205 | + frame.listenTo(button) |
| 206 | + frame.reactions += { |
| 207 | + case ButtonClicked(`button`) => showNewWindow() |
| 208 | + } |
| 209 | + |
| 210 | + //Center the button in a panel with some space around it. |
| 211 | + val pane = new FlowPanel() { |
| 212 | + border = Swing.EmptyBorder(5, 5, 5, 5) |
| 213 | + contents += button |
| 214 | + } |
| 215 | + pane |
| 216 | + } |
| 217 | + |
| 218 | +} |
| 219 | + |
| 220 | +class MyFrame extends Frame { |
| 221 | + title = "A window" |
| 222 | + |
| 223 | + //This button lets you close even an undecorated window. |
| 224 | + val button = new Button("Close window") { |
| 225 | + xLayoutAlignment = java.awt.Component.CENTER_ALIGNMENT |
| 226 | + } |
| 227 | + |
| 228 | + //Place the button near the bottom of the window. |
| 229 | + contents = new BoxPanel(Orientation.Vertical) { |
| 230 | + contents += Swing.VGlue |
| 231 | + contents += button |
| 232 | + contents += Swing.VStrut(5) |
| 233 | + } |
| 234 | + // |
| 235 | + listenTo(button) |
| 236 | + reactions += { |
| 237 | + case ButtonClicked(`button`) => |
| 238 | + visible = false |
| 239 | + dispose() |
| 240 | + } |
| 241 | + preferredSize = new Dimension(150, 150) |
| 242 | + pack() |
| 243 | + visible = true |
| 244 | + override def closeOperation() = { |
| 245 | + close |
| 246 | + } |
| 247 | +} |
| 248 | + |
| 249 | +class MyFrameUndecorated extends Frame with RichWindow.Undecorated { |
| 250 | + visible = false |
| 251 | + //This button lets you close even an undecorated window. |
| 252 | + val button = new Button("Close window") { |
| 253 | + xLayoutAlignment = java.awt.Component.CENTER_ALIGNMENT |
| 254 | + } |
| 255 | + |
| 256 | + //Place the button near the bottom of the window. |
| 257 | + //Undecorated windows are not supported in scala swing. |
| 258 | + contents = new BoxPanel(Orientation.Vertical) { |
| 259 | + contents += Swing.VGlue |
| 260 | + contents += button |
| 261 | + contents += Swing.VStrut(5) |
| 262 | + } |
| 263 | + // |
| 264 | + listenTo(button) |
| 265 | + reactions += { |
| 266 | + case ButtonClicked(`button`) => |
| 267 | + visible = false |
| 268 | + dispose() |
| 269 | + } |
| 270 | + preferredSize = new Dimension(150, 150) |
| 271 | + pack() |
| 272 | + visible = true |
| 273 | + override def closeOperation() = { |
| 274 | + close |
| 275 | + } |
| 276 | +} |
| 277 | + |
| 278 | +object FrameDemo2 extends SimpleSwingApplication { |
| 279 | + //Creates an icon-worthy Image from scratch. |
| 280 | + def createFDImage(): Image = { |
| 281 | + //Create a 16x16 pixel image. |
| 282 | + val bi = new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB) |
| 283 | + //Draw into it. |
| 284 | + val g: Graphics = bi.getGraphics() |
| 285 | + g.setColor(Color.BLACK); |
| 286 | + g.fillRect(0, 0, 15, 15) |
| 287 | + g.setColor(Color.RED) |
| 288 | + g.fillOval(5, 3, 6, 6) |
| 289 | + |
| 290 | + //Clean up. |
| 291 | + g.dispose() |
| 292 | + |
| 293 | + //Return it. |
| 294 | + bi |
| 295 | + } |
| 296 | + |
| 297 | + // Returns an Image Option or None. |
| 298 | + def getFDImage(): Option[Image] = { |
| 299 | + val imgURL: URL = getClass().getResource("/scala/swing/examples/tutorials/images/FD.jpg"); |
| 300 | + if (imgURL != null) { |
| 301 | + return Some(new ImageIcon(imgURL).getImage) |
| 302 | + } else { |
| 303 | + return None |
| 304 | + } |
| 305 | + } |
| 306 | + |
| 307 | + lazy val top = new Frame() { |
| 308 | + title = "FrameDemo2" |
| 309 | + //Use the Java look and feel. This needs to be done before the frame is created |
| 310 | + //so the companion object FrameDemo2 cannot simply extend SimpleSwingApplcation. |
| 311 | + try { |
| 312 | + UIManager.setLookAndFeel( |
| 313 | + UIManager.getCrossPlatformLookAndFeelClassName()); |
| 314 | + } catch { |
| 315 | + case e: Exception => ; |
| 316 | + } |
| 317 | + //Make sure we have nice window decorations. |
| 318 | + JFrame.setDefaultLookAndFeelDecorated(true); |
| 319 | + JDialog.setDefaultLookAndFeelDecorated(true); |
| 320 | + //Create and set up the content pane. |
| 321 | + val demo = new FrameDemo2(); |
| 322 | + } |
| 323 | + val bp: BorderPanel = new BorderPanel() { |
| 324 | + layout(top.demo.createOptionControls(top)) = BorderPanel.Position.Center |
| 325 | + layout(top.demo.createButtonPane(top)) = BorderPanel.Position.South |
| 326 | + } |
| 327 | + top.contents = bp |
| 328 | +} |
0 commit comments