Created
March 31, 2011 09:01
-
-
Save momania/896062 to your computer and use it in GitHub Desktop.
Over engineered Akka FSM scala Swing undecorated dialog using shapes and fading (why? because we can!)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package notification | |
import com.sun.awt.AWTUtilities | |
import java.awt.geom.RoundRectangle2D | |
import org.jdesktop.animation.timing.{TimingTarget, Animator} | |
import swing._ | |
import event.MouseClicked | |
import com.efgfp.creditspy.util.GuiUtil | |
import akka.actor.{FSM, Actor} | |
import org.jdesktop.animation.timing.Animator.{Direction, RepeatBehavior} | |
import swing.RichWindow.Undecorated | |
sealed trait DialogState | |
case object Hidden extends DialogState | |
case object Visible extends DialogState | |
case object Opening extends DialogState | |
case object Closing extends DialogState | |
sealed trait DialogAction | |
case object ShowDialog extends DialogAction | |
case object CloseDialog extends DialogState | |
private trait InternalNotification | |
private case object Opened extends InternalNotification | |
private case object Closed extends InternalNotification | |
class NotificationDialog(contentsComponent: Component) extends Actor with FSM[DialogState, Unit] with TimingTarget { | |
outer => | |
/** | |
* Dialog showing the component | |
*/ | |
val dialog = new Dialog with Undecorated { | |
peer.setAlwaysOnTop(true) | |
size = contentsComponent.preferredSize | |
location = GuiUtil.calculateLocationPoint(size) | |
contents = contentsComponent | |
val shape = new RoundRectangle2D.Double(0, 0, size.getWidth, size.getHeight, 15d, 15d) | |
AWTUtilities.setWindowShape(peer, shape) | |
listenTo(contentsComponent.mouse.clicks) | |
reactions += { | |
case MouseClicked(_, _, _, _, _) => | |
outer.self ! CloseDialog | |
} | |
} | |
/** | |
* Animator for the fading in and out | |
*/ | |
val animator = new Animator(600, 1d, RepeatBehavior.LOOP, this) | |
/** | |
* FSM states | |
*/ | |
when(Hidden) { | |
case Ev(ShowDialog) => | |
openDialog | |
goto(Opening) | |
} | |
when(Opening) { | |
case Ev(Opened) => | |
goto(Visible) | |
case Ev(CloseDialog) => | |
closeDialog | |
goto(Closing) | |
} | |
when(Visible) { | |
case Ev(CloseDialog) => | |
closeDialog | |
goto(Closing) | |
} | |
when(Closing) { | |
case Ev(Closed) => | |
stop | |
} | |
whenUnhandled{ | |
case unhandled => | |
stay | |
} | |
onTermination{ | |
case StopEvent(_, _, _) => | |
dialog.close | |
dialog.dispose | |
} | |
startWith(Hidden, ()) | |
initialize | |
/** | |
* Fading dialog in and out | |
*/ | |
private def openDialog() = { | |
AWTUtilities.setWindowOpacity(dialog.peer, 0f) | |
dialog.open | |
animator.setStartFraction(0.0f) | |
animator.setStartDirection(Direction.FORWARD) | |
animator.start | |
} | |
private def closeDialog() = { | |
if (animator.isRunning) { | |
animator.stop | |
} | |
animator.setStartFraction(1.0f) | |
AWTUtilities.setWindowOpacity(dialog.peer, 1.0f) | |
animator.setStartDirection(Direction.BACKWARD) | |
animator.start | |
} | |
/** | |
* Timer event methods | |
*/ | |
def timingEvent(fraction: Float) = { | |
AWTUtilities.setWindowOpacity(dialog.peer, fraction) | |
} | |
def end() = { | |
animator.getStartDirection match { | |
case Direction.BACKWARD => self ! Closed | |
case Direction.FORWARD => self ! Opened | |
} | |
} | |
def repeat() = {} | |
def begin() = {} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import akka.actor.Actor | |
import swing.Label | |
import java.util.concurrent.TimeUnit | |
import org.multiverse.api.latches.StandardLatch | |
import java.awt.Dimension | |
object NotificationApp extends Application { | |
val helloLabel = new Label { | |
text = "Hello FSM Dialog!" | |
preferredSize = new Dimension(300, 100) | |
} | |
val closedLatch = new StandardLatch | |
val notificationDialog = Actor.actorOf(new NotificationDialog(helloLabel) { | |
onTransition { (from, to) => if (to == Closed) closedLatch.open } | |
}).start | |
notificationDialog ! ShowDialog | |
TimeUnit.SECONDS.sleep(4) | |
notificationDialog ! CloseDialog | |
closedLatch.tryAwait(2, TimeUnit.SECONDS) | |
exit(0) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment