Bark! Growl Like Notifications for Flex

* I’ve updated the source code for the new Flex 4 beta 2. I’ve also fixed the null pointer error. You can download it here or checkout the latest from the Github.

Bark Logo

Introducing Bark! a notification framework for Flex modeled after the uber-awesome Growl framework for the Mac.

Bark in action.

Bark in action.

Recently, I’ve worked on several projects where I needed a Growl like notification to alert users of various events happening in the background. I did a Google search for Flex Growl and came across several solutions for Air and Growl but not many results for a web-based solution. I did come across Francis Lukesh’s Rawr! component. While I liked the result and thought it was well-thought out and implemented, I wanted a more general framework and less  dependencies on any non-Flex framework code (Rawr! was written using the HydraFramework and uses Degrafa for skinning). Originally, I intended to write the framework using the Flex 3 SDK, but I had been playing around with the new Flex 4 beta and was very impressed with the ease of skinning components. I thought here was a perfect opportunity to get my feet wet with Flex 4. I know I’ve possibly condemned myself to rewriting code as the SDK evolves from beta to production but I thought it was worth it for the improved functionality and ease of use. I might consider writing a Flex 3 version if there is a enough demand. You can check out a demo here (view source is enabled) and download the source code here. You can also checkout the source code from github here. Any comments or suggestions welcome.

Features:

  • Utilizes the new Flex 4 Beta SDK for improved skinning ability and other improvements.
  • Notifications are completely configurable. The title, description, duration, icon, and renderer can all be configured using the Notification object.
  • Multiple skins and styles can be setup using the type property of the Notification object. If the type property is set it will be used as the styleName for the renderer. This makes it easy to have multiple skins for a specific renderer (see the demo for an example of this).
  • Custom renderers can easily be specified using the renderer property on the Notification object.
  • Notification events can be dispatched anywhere in the display list to trigger a notification display. Once the NotificationManager is initialized it will listen for all notification events that bubble up the display list (by default it listens for events on the top level application but you can also pass in a custom display object to listen to).
  • Callback in place for notification renderer clicks. Simply listen for a NotificationEvent.notificationItemClick event on the notification object. * Note – calling preventDefault() on the event will stop the renderer from being removed  from the display list.
  • Hide and show effects for the notifications renderers are customizable globally using the NotificationManager.

To Do:

  • Switch notification renderer layout to use the new Flex 4 layouts for more flexibility and configuration options.
  • Maybe implement Flex 3 version depending on demand.
  • Documentation
  • More examples
Share and Enjoy:
  • Print this article!
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks

27 Comments

  1. Nathan Hinish says:

    Hey Tyler,

    I’ve been using your library for a project at work. Great job on this notification framework.

    I did notice that sometimes I get a NULL reference error. It’s attributed to Line 515 of NotificationManager, where timer is coming back as NULL…

    var timer:Timer = data.timer;
    timer.reset();
    timer.start();

    I simply wrapped the two timer method calls in a conditional to check that timer is not null like so…

    var timer:Timer = data.timer;
    if ( timer )
    {
    timer.reset();
    timer.start();
    }

    I know this doesn’t fix the root of the issue, but it will at least allow code to finish executing.

    Again, great job on this.

    Nate

  2. admin says:

    Hi Nate,

    I’m glad someone is using it! I’ll definitely look into that problem. Let me know if you run into another issues or have any improvement ideas. What kind of project are you using it in if you don’t mind my asking?

    Cheers
    Tyler

  3. Nathan Hinish says:

    Hey Tyler,

    The app I’m working on is a sort of control panel. We needed to allow for concurrency so we are using STOMP and ActiveMQ to push messages out, but we needed a way to very noticeably alert the user that some data had been updated. You’re notification system was a perfect fit, noticeable without being garish. :D

    I’ll let you know if I come across anything else.

    Nate

  4. Rob says:

    You should add some scroll bars to your example, as I couldn’t view it all on my laptop.

    It looks great, but the biggest issue I have with this and Rawr is that they don’t offer much in the way of getting events back. It would be good if you could pass through a closure to trigger on click, or on buttons?

    If I was using Flex 4 I would look into adding it myself :)

  5. [...] é o Bark! um solução Growl Like para Flex 4 e que usa Degrafa para [...]

  6. Timo says:

    I would love to see an Flex3 version of Bark. It is looking great

  7. Daniel says:

    This framework looks excellent, too bad I can’t migrate to flex 4 yet.

  8. Jaga says:

    Looks great, would be great to have one in Flex 3

  9. k.c. says:

    The null pointer as the first post stated was due to the roll over handler is being played before the notification is fully initialized. This happens when the notification is shown underneath the current mouse pointer. Similar npe happens when the notification is removing. I’ve a fix to the code. I can post a patch if someone is interested.

  10. admin says:

    Hi K.C.

    If you would like to fork the project on github and then we can merge it back into master. I’m glad people are using it.

  11. k.c. says:

    Hi Tyler,

    I was trying to look for any license terms come with ‘bark’. Could you provide us one or email me with details?

    Thanks.

  12. admin says:

    Yes,

    Copyright (c) 2009 Tyler Chesley

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the “Software”), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.

  13. Robx says:

    Hey Tyler,

    I have been trying to use Bark in a flex project but am running into issues with it. I was wondering what version of the flex 4 beta this was created in? I am running the beta 2 version (not the nightly builds) and I have issues with your code. Things I have run into are SimpleText no longer exists and is now just lable and spark.primitives.supportClasses.TextGraphicElement has changed to spark.components.supportClasses.TextBase. I found these changes listed on http://opensource.adobe.com/wiki/display/flexsdk/Spark+Text+Primitives+Decision

    Even after making these changes and having no errors I can’t get the code to work… thanks

  14. admin says:

    Hi Robx,

    Yes, Bark was originally written for the first Flex 4 beta. I have some down time today so I’m going to attempt to update Bark to be compatible with Flex beta 2. This will make it incompatible with the older Flex 4 beta though.

  15. admin says:

    I’ve updated the source code for Flex 4 beta 2. Also fixed the null pointer errors. Enjoy!

  16. TheBit says:

    Hi Tyler!

    Great job! Keep up this nice work!

    I’m wondering if its hard to create Flex 3 version? I’m run out of time for my project, and was going to try to do the migration for just my project quickly. I guess Spark skin can be replaced with something from Flex 3?

    Interesting if it has a lot of other Flex 4 specific parts?

  17. admin says:

    Thanks!

    I’m thinking that if you just create a Flex 3 specific notification renderer the rest of the framework should work. If I get a chance today I will take a look. Let me know how it goes if you do decide to try to port to Flex 3.

  18. Clay says:

    Quick question – how do you control the location of the notifications?

  19. Clay says:

    Another quick question – is it possible to have these appear when the application is minimized? I’ve found a couple of other alert window / growl type libraries, but this is by far the best. Unfortunately, popping up while minimized is a big deal :)

  20. TJ Downes says:

    Hey Tyler

    Looks like a great framework! Just an FYI, the package will not import into Flex 4 release SDK. I am going to give a shot at upgrading it, but figured you would want to know.

    java.lang.IllegalArgumentException: Component type spark.components.Group not found.
    at com.adobe.flexbuilder.mxmlmodel.NamespaceHelper.getXMLNamesForClass(NamespaceHelper.java:217)
    at com.adobe.flexbuilder.mxmlmodel.NamespaceHelper.getTagForClass(NamespaceHelper.java:169)
    at com.adobe.flexbuilder.designmodel.DesignModelManager.createMXMLModel(DesignModelManager.java:356)
    at com.adobe.flexide.mxml.core.utils.ProjectPrivateDataManager.createEmptyPrivateDataFile(ProjectPrivateDataManager.java:117)
    at com.adobe.flexide.mxml.core.utils.ProjectPrivateDataManager.getPrivateDataModel(ProjectPrivateDataManager.java:79)
    at com.adobe.flexide.fonts.FontMapManager.(FontMapManager.java:69)
    at com.adobe.flexide.exportimport.library.ImportLibraryOperation.performFontResolving(ImportLibraryOperation.java:552)
    at com.adobe.flexide.exportimport.library.ImportLibraryOperation.preprocessExpandedProject(ImportLibraryOperation.java:534)
    at com.adobe.flexide.exportimport.library.ImportLibraryOperation$1.run(ImportLibraryOperation.java:245)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1800)
    at com.adobe.flexide.exportimport.library.ImportLibraryOperation.performImport(ImportLibraryOperation.java:261)
    at com.adobe.flexide.exportimport.library.ImportLibraryOperation.run(ImportLibraryOperation.java:152)
    at com.adobe.flexbuilder.exportimport.importwizard.ArchivedProjectImporter.importFlexProject(ArchivedProjectImporter.java:510)
    at com.adobe.flexbuilder.exportimport.importwizard.ImportWizard.importProject(ImportWizard.java:241)
    at com.adobe.flexbuilder.exportimport.importwizard.ImportWizard$1.execute(ImportWizard.java:111)
    at org.eclipse.ui.actions.WorkspaceModifyOperation$1.run(WorkspaceModifyOperation.java:106)
    at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1800)
    at org.eclipse.ui.actions.WorkspaceModifyOperation.run(WorkspaceModifyOperation.java:118)
    at org.eclipse.jface.operation.ModalContext.runInCurrentThread(ModalContext.java:464)
    at org.eclipse.jface.operation.ModalContext.run(ModalContext.java:372)
    at org.eclipse.jface.wizard.WizardDialog.run(WizardDialog.java:944)
    at com.adobe.flexbuilder.exportimport.importwizard.ImportWizard.performFinish(ImportWizard.java:117)
    at org.eclipse.jface.wizard.WizardDialog.finishPressed(WizardDialog.java:752)
    at org.eclipse.jface.wizard.WizardDialog.buttonPressed(WizardDialog.java:373)
    at org.eclipse.jface.dialogs.Dialog$2.widgetSelected(Dialog.java:624)
    at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:228)
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003)
    at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3910)
    at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3503)
    at org.eclipse.jface.window.Window.runEventLoop(Window.java:825)
    at org.eclipse.jface.window.Window.open(Window.java:801)
    at org.eclipse.ui.internal.handlers.WizardHandler$Import.executeHandler(WizardHandler.java:146)
    at org.eclipse.ui.internal.handlers.WizardHandler.execute(WizardHandler.java:273)
    at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:294)
    at org.eclipse.core.commands.Command.executeWithChecks(Command.java:476)
    at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:508)
    at org.eclipse.ui.internal.handlers.HandlerService.executeCommand(HandlerService.java:169)
    at org.eclipse.ui.internal.handlers.SlaveHandlerService.executeCommand(SlaveHandlerService.java:241)
    at org.eclipse.ui.internal.actions.CommandAction.runWithEvent(CommandAction.java:157)
    at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:584)
    at org.eclipse.jface.action.ActionContributionItem.access$2(ActionContributionItem.java:501)
    at org.eclipse.jface.action.ActionContributionItem$5.handleEvent(ActionContributionItem.java:411)
    at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
    at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003)
    at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3910)
    at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3503)
    at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2405)
    at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2369)
    at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2221)
    at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:500)
    at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
    at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:493)
    at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
    at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:113)
    at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:194)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
    at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:368)
    at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:559)
    at org.eclipse.equinox.launcher.Main.basicRun(Main.java:514)
    at org.eclipse.equinox.launcher.Main.run(Main.java:1311)

  21. TJ Downes says:

    My mistake. It appears you have to have the Flex 4 SDK set as your default SDK in Flash Builder. Once you do this, the import of the fxpl file works fine.

  22. [...] Tyler Chesley’s Blog » Blog Archive » Bark! Growl Like Notifications for Flex – Flex, Acti… (tags: flex growl library flex4) [...]

  23. Steve says:

    Hey Tyler,

    I love the idea & look of your project but I’m having a problem. It could be that I’m an idiot as I’ve only been using Flex for a week or so. I’m basically getting an error (pasted at the bottom) while trying to add a notification. Is this framework suitable for a desktop app run in AIR? Sorry to bug you & for a potentially silly question, but I’d love to use it…

    anywho..
    Cheers

    There’s a load more to this but here’s the first few lines:

    Error: Skin for NotificationRenderer72 cannot be found.
    at spark.components.supportClasses::SkinnableComponent/attachSkin()[E:\dev\4.0.0\frameworks\projects\spark\src\spark\components\supportClasses\SkinnableComponent.as:632]
    at spark.components.supportClasses::SkinnableComponent/validateSkinChange()[E:\dev\4.0.0\frameworks\projects\spark\src\spark\components\supportClasses\SkinnableComponent.as:405]
    at spark.components.supportClasses::SkinnableComponent/createChildren()[E:\dev\4.0.0\frameworks\projects\spark\src\spark\components\supportClasses\SkinnableComponent.as:368]

  24. admin says:

    Hi Steve,

    Are you using the latest version? You can download it here:

    http://www.blog.tylerchesley.org/examples/Bark-Flex-beta-2.fxpl

    Let me know if you are still having problems after you try the latest version.

    Bark was mainly meant for web applications. You could use it in an air application but it might not do what you expect it to. It won’t work like Growl because it doesn’t natively integrate with the OS.

  25. Steve says:

    Hi, thanks for the reply! It is that version I’m using. When you say it may not behave like I’d expect do you mean maybe that I wouldn’t be able to position the notifications at a corner of the screen?

    If you know of any AIR based notification system similar to yours, I’d love to hear about them. I’m looking around but many of them seem to be web based :(

    Thanks..

  26. ninjate says:

    I need to show a notification while a modal pop up windows is already open. But; this scenario is not working with this component, which; I guess because of the PopUpManager conflict…?
    Any way to solve this?

  27. admin says:

    Hmm…it should work. Have you tried using PopUpManager.bringToFront()?

Leave a Reply