PureMVC Architects Lounge

Announcements and General Discussion => General Discussion => Topic started by: danieleUg on November 05, 2007, 04:45:02



Title: Popup Window
Post by: danieleUg on November 05, 2007, 04:45:02
Hi all, I want to share with you a little code that have found usefull in the project that I just build with PureMVC.
A lot of time I must to open different popup windows each with own Component/Mediator, I have written this code inside ApplicationFacade:

:
import flash.display.Sprite;
import mx.core.Application
import mx.core.IFlexDisplayObject;
import mx.managers.PopUpManager;

public static function openPopUpWindow( ComponentClass:Class, MediatorClass:Class ):void
{
var window:IFlexDisplayObject = PopUpManager.createPopUp( Application.application as Sprite, ComponentClass, true );

ApplicationFacade.getInstance().registerMediator( new MediatorClass( window ) );
PopUpManager.centerPopUp( window );
}

public static function closePopUpWindow( window:IFlexDisplayObject, mediatorName:String ):void
{
PopUpManager.removePopUp( window );
ApplicationFacade.getInstance().removeMediator( mediatorName );
}

For open the window you have to call ApplicationFacade.openPopUpWindow( MyComponent, MyComponentMediator );
and for close the window: ApplicationFacade.closePopUpWindow( myComponentInstance, MyComponentMediator.NAME );

Best,
   Daniele


Title: Re: Popup Window
Post by: puremvc on November 06, 2007, 12:06:03
Daniele,

This is a great answer to the problem of popups. My existing solution involves having an AbstractPopupMediator which Mediators that will also need to invoke popups extend. But that just bloats those mediators with more responsibility. This is simpler, so I like it much better.

However, the placement on the Facade is one to be considered.

The Facade is by design, a handy, central place for things. But some things make sense there and some things tend to get put there because it's easy. After putting one thing there it becomes a lot easier to put the next thing there, and so on until it becomes bloated. Sort of like the Broken Window theory. http://en.wikipedia.org/wiki/Fixing_Broken_Windows

I've seen this happening in my own coding, so I recognize it well.

Since these methods are static, I would suggest a more appropriate place to put them might be a class like: com.me.myapp.view.managers.PopupManager.

-=Cliff>


Title: Re: Popup Window
Post by: danieleUg on November 07, 2007, 04:34:31
Hi Cliff,
I like the idea to have a manager class.

I have a suggestion, why don't create a wiki where the users can put solutions like it?



Title: Re: Popup Window
Post by: puremvc on November 07, 2007, 06:28:07
I'm actually working on the community integration problem this week.

There are roughly a bazillion and 42 things we need to have happen, and I'd like the process to go smoothly and not become a huge mess that has to be cleaned up constantly because their wasn't a plan to start with.

So the fisrt step as I see it is building a task force of people who want to lend a hand with tools or porting or docs, etc.

I'm building a wizard to allow signups to the task force, where you can choose or suggest your area of interest in helping out. This will get you access to one of a number of private task force forums where we can hash out who will do what, where and how they'll do it.

This will encompass supported sub-projects' such as your app skeleton, with svn repository, wiki, etc.

I am inspired by the Apache Foundation on this. Have a look at the Apache.org site.
-=Cliff>


Title: Re: Popup Window
Post by: danieleUg on November 07, 2007, 11:24:53
You have had a good idea!


Title: Re: Popup Window
Post by: danieleUg on November 12, 2007, 11:42:07
Hi Cliff,
I have a little question, if a have a button that open a popupWindow, what's the best way to do it?

- the Component dispatchEvent
- the Mediator capture the event and sendNotification for execute the Command
- the Command call the PopupManger for open the popupWindow (with the PopupManger is only one line of code).

or

- the Component dispatchEvent
- the Mediator capture the event and call the PopupManger for open the popupWindow


or

- the Component call the PopupManger for open the popupWindow



Title: Re: Popup Window
Post by: puremvc on November 12, 2007, 12:03:23
I would go with the second flow you described:

- the Component dispatchEvent
- the Mediator capture the event and call the PopupManger for open the popupWindow


As you say, no need for the Command if it's only going to make that call (first flow).

But we don't want the actual view components to know any more of the PureMVC side of things than they absolutely have do (third flow).

-=Cliff>


Title: Re: Popup Window
Post by: kmorland on March 17, 2008, 05:33:12
Hello,

I am having problems with creating an PopUp Window.  I receive an error message when trying to create the PopUp Window.  Here is the error message:

TypeError: Error #1007: Instantiation attempted on a non-constructor.
        at mx.managers::PopUpManagerImpl/createPopUp()
        at mx.managers::PopUpManager$/createPopUp()
        at com.managers.popup::PopManager$/openPopUpWindow()
        at org.puremvc.user.view::RepDetailsMediator/onUploadPopUp()
        at flash.events::EventDispatcher/dispatchEventFunction()
        at flash.events::EventDispatcher/dispatchEvent()
        at mx.core::UIComponent/dispatchEvent()
        at org.puremvc.user.view.components::RepDetails/uploadPopUpFunc()
        at org.puremvc.user.view.components::RepDetails/___Button1_click()

I have a canvas that sends an event to its mediator which calls the method to create the popup.  I created an UploadForm and UploadFormMediator and a PopManager class.

:
package com.managers.popup
{
import flash.display.Sprite;
import mx.core.Application;
import mx.core.IFlexDisplayObject;
import mx.managers.PopUpManager;
import org.puremvc.user.ApplicationFacade;


public class PopManager extends PopUpManager
{
public static function openPopUpWindow( ComponentClass:Class, MediatorClass:Class ):void
    {
        var window:IFlexDisplayObject = PopUpManager.createPopUp( Application.application as Sprite, ComponentClass, true );

        ApplicationFacade.getInstance().registerMediator( new MediatorClass( window ) );
        PopUpManager.centerPopUp( window );
    }

    public static function closePopUpWindow( window:IFlexDisplayObject, mediatorName:String ):void
    {
        PopUpManager.removePopUp( window );
        ApplicationFacade.getInstance().removeMediator( mediatorName );
    }
}
}

Here is the RepDetailsMediator.as
:
/*
  PureMVC Architecture 101 Course
Copyright(c) 2007 FutureScale, Inc. All rights reserved.
 */
package org.puremvc.user.view
{
import mx.controls.Alert;
import flash.events.Event;

import org.puremvc.interfaces.IMediator;
import org.puremvc.interfaces.INotification;
import org.puremvc.patterns.mediator.Mediator;
import org.puremvc.patterns.observer.Notification;

import org.puremvc.common.model.vo.UserVO;
import org.puremvc.common.model.UserProxy;
import org.puremvc.common.model.RepDetailsProxy;

import org.puremvc.user.ApplicationFacade;
import org.puremvc.user.view.components.NewUserForm;
import org.puremvc.user.view.components.RepDetails;
import org.puremvc.user.view.components.UploadForm;
import com.managers.popup.PopManager;

public class RepDetailsMediator extends Mediator implements IMediator
{

public static const NAME:String = "RepDetailsMediator";
private var userProxy:UserProxy;
private var repDetailsProxy:RepDetailsProxy;
private var UploadForm:Class;
private var UploadFormMediator:Class;

public function RepDetailsMediator( viewComponent:Object )
{

super( viewComponent );

repDetails.addEventListener( RepDetails.CHECKBOX_SELECTED, onCheckBoxSelected );
repDetails.addEventListener( RepDetails.UPLOAD_POPUP, onUploadPopUp );

userProxy = facade.retrieveProxy( UserProxy.NAME ) as UserProxy;
repDetailsProxy = facade.retrieveProxy( RepDetailsProxy.NAME ) as RepDetailsProxy;

}


private function get repDetails():RepDetails
{
return viewComponent as RepDetails;
}

override public function getMediatorName():String
{
return NAME;
}

private function onCheckBoxSelected( event:Event ) : void
{
trace("Here Here Data:" + repDetails.checkedData);
userProxy.updateProject(repDetails.checkedData);
}

private function onUploadPopUp(event:Event):void
{
PopManager.openPopUpWindow( UploadForm, UploadFormMediator );
    }

override public function listNotificationInterests():Array
{
return [
ApplicationFacade.NEW_USER_FORM
   ];
}

override public function handleNotification( note:INotification ):void
{
switch ( note.getName() )
{
case ApplicationFacade.NEW_USER_FORM:
repDetails.projectData = repDetailsProxy.projectData;
repDetails.statesData = repDetailsProxy.statesData;
repDetails._selectedDate = repDetailsProxy.getNow18Years();
}
}
}
}

Any help or suggestions is much needed and appreciated.

Thanks,
Kevin



Title: Re: Popup Window
Post by: kurtfusion on July 22, 2008, 10:50:54

Thanks for posting this example I have created a simple class that I'm using to handle my popup's. I have added stackWindows and closeAll . I hope this helps someone else.

To use

import PopManager;

PopManager.stackWindows(YourView);
PopManager.closeAll(YourView);
PopManager.openPopUpWindow(YourView,YourViewMediator,true);

package
{
   import ApplicationFacade;
   
   import flash.display.Sprite;
   import flash.utils.getQualifiedClassName;
   
   import mx.core.Application;
   import mx.core.IFlexDisplayObject;
   import mx.managers.PopUpManager;

   public class PopManager
   {
      
      public function PopManager()
      {
      }
      
      public static function stackWindows(ComponentClass:Class):void{
             for (var i:int = Application.application.systemManager.numChildren - 1;  i >= 0; i--) {
                    if(getQualifiedClassName(Application.application.systemManager.getChildAt(i))==getQualifiedClassName(ComponentClass)){
                        var window:IFlexDisplayObject = Application.application.systemManager.getChildAt(i);
                        window.x = i * 30;
                        window.y = i * 30;
                    }
                }
          }
         
      public static function closeAll(ComponentClass:Class):void{
                for (var i:int = Application.application.systemManager.numChildren - 1;  i >= 0; i--) {
                    if(getQualifiedClassName(Application.application.systemManager.getChildAt(i)) == getQualifiedClassName(ComponentClass)){
                        Application.application.systemManager.removeChildAt(i);
                    }
                }
            }
      
      public static function openPopUpWindow( ComponentClass:Class, MediatorClass:Class, modal:Boolean):void
      {
         var window:IFlexDisplayObject = PopUpManager.createPopUp( Application.application as Sprite, ComponentClass, modal );
      
         ApplicationFacade.getInstance().registerMediator( new MediatorClass( window ) );
         PopUpManager.centerPopUp( window );
      }
      
      public static function closePopUpWindow( window:IFlexDisplayObject, mediatorName:String ):void
      {
         PopUpManager.removePopUp( window );
         ApplicationFacade.getInstance().removeMediator( mediatorName );
      }
      
   }
}


Title: Re: Popup Window
Post by: flexphp on July 28, 2008, 04:55:52
Daniele,

This is a great answer to the problem of popups.
...
Since these methods are static, I would suggest a more appropriate place to put them might be a class like: com.me.myapp.view.managers.PopupManager.

-=Cliff>


Why not put it in the ApplicationMediator? It is already in charge of displaying things like login screen, splash screen...
The ApplicationMediator just listen for a notification to popup.
This avoid creating a new dir & a new file (that has to be imported)

Cheers,
Patrick


Title: Re: Popup Window
Post by: puremvc on July 28, 2008, 08:22:07
It all depends on your ap as to how much or how little responsibility the ApplicationMediator is already loaded down with. If it's a lot, then this may just add to the bloat. By just concentrating the popup handling in one place to begin with, we make a clearly defined role for it.

Identifying the roles and responsibilities in your app is like starting a business and figuring out who's going to do what. In a very small app (or business), one actor may take on several roles. But if the venture grows, inevitably those few actors will be doing too much. Soon you'll find you need to offload some work onto an office manager (or a PopupManager).

So in more concrete terms, you can always put this functionality in your ApplicationMediator if its not doing much. Then if if gains more resposibility later, you can just refactor these bits into a Popupmanager.

-=Cliff>


Title: Re: Popup Window
Post by: dbasch on January 16, 2009, 09:53:28
Here is the solution that I ended up using for this particular problem:

:
public class ApplicationMediator extends Mediator implements IMediator
{
public static const NAME:String = 'ApplicationMediator';

public function ApplicationMediator( viewComponent:Object ) {
super( NAME, viewComponent );
}

override public function listNotificationInterests():Array {
return [ApplicationFacade.POP_UP_VC_ADD];
}

override public function handleNotification( note:INotification ):void {
    addToNotificationsReceived( note );
switch ( note.getName() ) {
   case ApplicationFacade.POP_UP_VC_ADD:
this.onPopUpAdd(note.getBody());
    break;   
}
}

private function onPopUpAdd(popUp):void
{
                    PopUpManager.addPopUp(popUp, this.viewComponent, true);
                    PopUpManager.centerPopUp(popUp);
}


Title: Re: Popup Window
Post by: JJfutbol on January 23, 2009, 11:48:49
Hmm, man there really is a ton of different solutions to the same problem because I'm surely doing it different then all of you. :) So figured I'd share what I do since its sooo cool!

I actually use commands to create popUps. I like it and feel the encapsulation is better there then say in a mediator. Plus this gives me the added flexibility of calling it from anywhere. I do the same for new Window's in AIR apps because most of the time these popUps/windows I also need to create using keyboard shortcuts.

My naming convention always starts with the word Open for the command. So if I have an IdeaEditor component (Window) or a VoteOrganizer (PopUp->TitleWindow) I would call the commands as:

  • OpenIdeaEditorCommand
  • OpenVoteOrganizerCommand

I really like this approach since not only do I have that functionality all in one place in case it needs to change but I can have encapsulated the appropriate logic for determining if the window is already opened then I just bring the window to the front or preventing a new popUp to open if one already exists.


Title: Re: Popup Window
Post by: puremvc on January 25, 2009, 07:38:36
What listens for the popup to close and other events it might raise?
-=Cliff>


Title: Re: Popup Window
Post by: JJfutbol on January 25, 2009, 11:06:25
PopUps

Excellent question! I've found it very helpful to have an AbstractMediator that will retrieve any common Proxies required by all mediators for such things like Configuration, Identity, sometimes even a specific entity, etc.

Since I've had projects that require a few PopUps I've found it handy to create an AbstractPopUpMediator which extends the AbstractMediator. All the AbstractPopUpMediator does is define a private getter for the viewComponent property called "popUp" where its cast as an IFlexDisplayObject. On registration I add 2 event listeners for when the popUp is closed or when you mouse down on the outside area of a popup.

In this case I have that code in a base class but when I first did this I would always have it in the PopUp's actual mediator. Either one works well just depends on preference. I had asked awhile back and you were kind enough to respond Cliff about Mediators removing them self from the Facade so in this case I have the popUp Mediator do that which I find simple and easy. I haven't had a need for having that code in a command but a real great need for opening and determining how one is opened with a command.

Windows

For windows in AIR I have the same approach regarding a command to open one. I've had a real need for this since I have logic that has to figure out if the window for a VO is already open, if it is just activate it (bring it to the front and set focus) otherwise one needs to be created. In this case the command is called OpenIdeaEditorCommand and my mx:Window component is called IdeaEditor (think exactly like creating a new email with Apple Mail).

My case is that what makes the component unique is the IdeaVO. I use Flex's UIDUtil class and call the getUID(obj) method passing in an IdeaVO instance to make sure I have a unique id for each instance. This is how I register mediators since I use that UID as a name! I check if their is a mediator registered with that name and if there is I know a window is already open (in this case for an existing idea that is being edited) so I send a ACTIVATE_IDEA_EDITOR notification which that Mediator responds too by calling the viewComponent's activate() method.

If the mediator is not registered I know I need to create a new IdeaEditor so that is done in the command as well as creating and registering the new mediator. All event handlers are taken care of within the mediator, not the command! So if you close the window the mediator listens for a close event so it can remove itself from the Facade. Hot! :) Cliff, I showed this at the set of PureMVC presentations at MAX since it is an AIR client I built using PureMVC.

As I've mentioned to you I'd like to do a series of short presentations/recordings for the PureMVC site since I think I've really nailed the Mediator-Component relationship and have some neat examples on how best to use Commands. Also some advice on how to determine what should be an individual component, when to know to use a command, etc.


Title: Re: Popup Window
Post by: Joel Hooks on January 25, 2009, 11:55:44

Windows

For windows in AIR I have the same approach regarding a command to open one. I've had a real need for this since I have logic that has to figure out if the window for a VO is already open, if it is just activate it (bring it to the front and set focus) otherwise one needs to be created. In this case the command is called OpenIdeaEditorCommand and my mx:Window component is called IdeaEditor (think exactly like creating a new email with Apple Mail).

My case is that what makes the component unique is the IdeaVO. I use Flex's UIDUtil class and call the getUID(obj) method passing in an IdeaVO instance to make sure I have a unique id for each instance. This is how I register mediators since I use that UID as a name! I check if their is a mediator registered with that name and if there is I know a window is already open (in this case for an existing idea that is being edited) so I send a ACTIVATE_IDEA_EDITOR notification which that Mediator responds too by calling the viewComponent's activate() method.

If the mediator is not registered I know I need to create a new IdeaEditor so that is done in the command as well as creating and registering the new mediator. All event handlers are taken care of within the mediator, not the command! So if you close the window the mediator listens for a close event so it can remove itself from the Facade. Hot! :) Cliff, I showed this at the set of PureMVC presentations at MAX since it is an AIR client I built using PureMVC.

This is exactly how I handle Windows in AIR also. It works really well. I usually create AbstractIdeaWindow components as well to provide a similar interface across the related components - in addition to the AbstractIdeaWindowMediator (which extends my common AbstractMediator).

All of my VOs (and database tables) carry a UID property with the constructors passing a new UID (if it isn't already there). This is great because I don't have to wait for the object to come back from the service with an ID property and can track it instantly in my application for interface items (Windows) unique to the object.

This is the typical execute method in my OpenWindowCommand classes:

:
override public function execute(notification:INotification):void
{
var caseVO:CaseVO = notification.getBody() as CaseVO;
if(!caseVO)
return

var caseWindow:CaseMediaWindow;
var caseWindowMediator:CaseMediaWindowMediator;

if(facade.hasMediator(CaseMediaWindowMediator.NAME+caseVO.UID))
{
caseWindow = facade.retrieveMediator( CaseMediaWindowMediator.NAME+caseVO.UID ).getViewComponent() as CaseMediaWindow;
caseWindow.activate();
caseWindow.restore();
caseWindow.orderToFront();
}
else
{
caseWindow = new CaseMediaWindow()
caseWindow.open();
caseWindowMediator = new CaseMediaWindowMediator(caseWindow, caseVO);
facade.registerMediator(caseWindowMediator)
}
}


Title: Re: Popup Window
Post by: JJfutbol on January 25, 2009, 08:50:57
Joel, have I ever told you have impeccable taste when it comes to applying solutions as yours with commands. :) If only other people had such great as us! I really want to share examples like these since I think most people don't really find much use for commands but they can prove to be quite helpful in encapsulating logic.


Title: Re: Popup Window
Post by: dierre on April 14, 2009, 03:11:05
Hi Daniele. I have a question. Your method is working but how can I load external information?