Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1] 2
Print
Author Topic: Popup Window  (Read 38417 times)
danieleUg
Courseware Beta
Full Member
***
Posts: 28


View Profile Email
« 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
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 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>
Logged
danieleUg
Courseware Beta
Full Member
***
Posts: 28


View Profile Email
« Reply #2 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?

Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #3 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>
Logged
danieleUg
Courseware Beta
Full Member
***
Posts: 28


View Profile Email
« Reply #4 on: November 07, 2007, 11:24:53 »

You have had a good idea!
Logged
danieleUg
Courseware Beta
Full Member
***
Posts: 28


View Profile Email
« Reply #5 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

Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #6 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>
Logged
kmorland
Courseware Beta
Newbie
***
Posts: 6


View Profile Email
« Reply #7 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

Logged
kurtfusion
Newbie
*
Posts: 1


View Profile Email
« Reply #8 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 );
      }
      
   }
}
Logged
flexphp
Jr. Member
**
Posts: 17


View Profile Email
« Reply #9 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
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #10 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>
Logged
dbasch
Jr. Member
**
Posts: 17


View Profile Email
« Reply #11 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);
}
Logged
JJfutbol
Sr. Member
****
Posts: 53


View Profile WWW Email
« Reply #12 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.
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #13 on: January 25, 2009, 07:38:36 »

What listens for the popup to close and other events it might raise?
-=Cliff>
Logged
JJfutbol
Sr. Member
****
Posts: 53


View Profile WWW Email
« Reply #14 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.
Logged
Pages: [1] 2
Print