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: Desktop Citizen Event.CLOSING  (Read 12724 times)
Ondina
Sr. Member
****
Posts: 86


View Profile Email
« on: March 19, 2009, 03:43:05 »

Hi Cliff

Desktop Citizen is great. Thanks again for this utility.

I would like to be able to prevent an accidental closing of the WindowedApplication and ask the users if they want to save the data before exiting the application.

In the WindowMediator of the utility there is:
 
stage.nativeWindow.addEventListener( Event.CLOSING, onWindowClosing );

and the method

protected function onWindowClosing( event:Event ):void

I can have a modal dialog  asking the users if they want to exit or not, if I modify it like this:

private var isWorkSaved:Boolean = false;
protected function onWindowClosing( event:Event ):void
{
if( !isWorkSaved )
   {
       event.preventDefault();
       Alert.show( "Would you like to save your work?", "Warning!",Alert.YES | Alert.NO, null, onAlertClose );
        }
}            
protected function onAlertClose( event:CloseEvent ):void
{
   if( event.detail == 1 )
   {
       isWorkSaved = true;
      stage.nativeWindow.visible = false;
      sendNotification( WindowCloseCommand.NAME );
      stage.nativeWindow.close();
   }
}

or I can send a notification inside the  onWindowClosing and have the modal dialog in my application somewhere and then from there sendNotification( WindowCloseCommand.NAME );

I don't know if it's ok with you if  I'd change it like this (copyright license?), but event if it was, isn't there another (better) way to achieve the same when I use DesktopCitizen   And also maybe in other situations I don't want to  have that modal dialog before exiting the application.

Ondina
Logged

~ Ondina ~
Ondina
Sr. Member
****
Posts: 86


View Profile Email
« Reply #1 on: March 21, 2009, 02:49:27 »

My application deals with sensitive data.
It is very important to prevent an accidental closing of the application when the data is in an unstable ( not saved ) state.
Also it is important to handle  situations where the application is idle for a certain amount of time.

Data loss prevention carries more weight  in my current project than  having the application remember its window size/position .

Since you are not responding I don't know if it's ok with you to have  your utility modified the way  I suggested in my previous post.

I just can assume that you don't want any changes,  therefore  I will have to handle the FlexEvent.IDLE and Event.CLOSING events without using DesktopCitizen.

It's a pity though because I like the DesktopCitizen utility.
Logged

~ Ondina ~
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #2 on: March 21, 2009, 06:30:07 »

Ondina,

Please don't make any assumptions based on lack of response within a certain timeframe. I only have so much bandwidth and just now a high volume coupled with an extremely busy work schedule has caused the posts to pile up a bit is all. But as always I am still plowing through it.

As to using a modified version of the utility, feel free to do so, there's no problem at all with that. That's the reason the source is available.

I don't think this is the exact code I would want to fold back into the project, but I think its pretty close. If there was a way to make this an optional hook, that might be nice, but you'd still need to be able to supply it the string. And the developer may not want a standard Alert box for their UI.

Is there no way to move some of this logic and user confirmation outside  of the util? Its an obvious improvement, but I'd like to be able to make it generic enough to be widely reusable.

If you don't have time to figure it out, and this works for your current app, go with your current change, and I'll think about it and eventually get to a solution that can be released.

Thanks for your input in this, I appreciate it.

-=Cliff> 
Logged
Ondina
Sr. Member
****
Posts: 86


View Profile Email
« Reply #3 on: March 21, 2009, 08:51:18 »

Ok, no more such assumptions from now on:)

I don't think this is the exact code I would want to fold back into the project, but I think its pretty close. If there was a way to make this an optional hook, that might be nice, but you'd still need to be able to supply it the string. And the developer may not want a standard Alert box for their UI.

Well, I'm not content with that solution either.
No matter if  there is an Alert or another way to get a confirmation from the user  - you are right - it should be optional and outside of the WindowMediator.

As a matter of fact in some situations I don't need the user's confirmation at all, I just need to now that the data is unstable and save it before letting the application close the window.
Also it would be the right time/place ( on Event.CLOSING ) for saving some other application related info/configs in the XML Database together with those window's metrics used by the DesktopCitizen.

I will give it a try and think of a solution despite my “unstable” puremvc-knowledge.
I'll post about it and if it won't be a good approach, it surely  won't be a problem for me to wait until you'll get more time for a really “pure” solution.

Thanks
Logged

~ Ondina ~
Ondina
Sr. Member
****
Posts: 86


View Profile Email
« Reply #4 on: March 21, 2009, 11:51:37 »

Look at this:

ApplicationFacade

registerCommand( DesktopCitizenConstants.WINDOW_OPEN, WindowOpenCommand );


ViewPrepCommand


var app:MultiAir = note.getBody() as MultiAir;
facade.registerMediator( new ApplicationMediator( note.getBody() as MultiAir ));
sendNotification( DesktopCitizenConstants.WINDOW_OPEN, app.stage, "1" );

Here I put the flag in the type of the Notification.    


ApplicationMediator

override public function handleNotification( note:INotification ):void
{
switch ( note.getName() ) {
case DesktopCitizenConstants.WINDOW_CLOSING:
if( !isWorkSaved )
{
Alert.show( "Would you like to save your work?", "Warning!",Alert.YES | Alert.NO, null, onAlertClose );
//or just saving
}
break;
....
}

private function onAlertClose( event:CloseEvent ):void
{
if( event.detail == 1 )
{
isWorkSaved = true;
sendNotification( WindowCloseCommand.NAME );
app.stage.nativeWindow.close();
}
}   

DesktopCitizenConstants

public static const WINDOW_CLOSING:String   = "DesktopCitizenWindowClosing";


WindowOpenCommand

var confirm_flag:String = note.getType();
sendNotification(WindowMediator.ENABLE_CONFIRM, confirm_flag);


WindowMediator

public static const ENABLE_CONFIRM:String   = "DesktopCitizenEnableConfirm";

override public function handleNotification( note:INotification ):void
{
switch ( note.getName() ) {
case ENABLE_CONFIRM:
needConfirm = note.getBody() as String;      
break;
...
}

private var needConfirm:String ;
protected function onWindowClosing( event:Event ):void
{
   if(needConfirm=="1"){
   stage.nativeWindow.visible = true;
   event.preventDefault();
   sendNotification( DesktopCitizenConstants.WINDOW_CLOSING);
   }else{
   stage.nativeWindow.visible = false;
       sendNotification( WindowCloseCommand.NAME );
       stage.nativeWindow.close();
}
}   

Not the best solution yet.
Logged

~ Ondina ~
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #5 on: March 22, 2009, 06:43:04 »

Looks like you're headed the right direction with this, though. I'd make the value of the confirm flag a constant rather than checking for "1" everywhere, but its shaping up.

-=Cliff>
Logged
Ondina
Sr. Member
****
Posts: 86


View Profile Email
« Reply #6 on: March 22, 2009, 08:00:37 »

I'd make the value of the confirm flag a constant rather than checking for "1" everywhere, but its shaping up.

Yes, that string is ugly.
I wanted to make it a Boolean, but I've got carried away by the note.type wich is a String... I don't know why I used the note.type anymore.

Actually now I think that there is no need for a flag.
If you want a confirmation before closing you send just  this:

sendNotification(WindowMediator.ENABLE_CONFIRM);
without anything else

and if you don't want to do anything on Event.CLOSING you don't send this notification.

Then in the WindowMediator
private var needConfirm:Boolean=false ;
...
override public function handleNotification( note:INotification ):void
{
switch ( note.getName() ) {
  case ENABLE_CONFIRM:
    needConfirm = true;
  break;
...
}
protected function onWindowClosing( event:Event ):void
{
if(needConfirm){
  event.preventDefault();
  sendNotification( DesktopCitizenConstants.WINDOW_CLOSING);
}else{
  stage.nativeWindow.visible = false;
  sendNotification( WindowCloseCommand.NAME );
  stage.nativeWindow.close();
}
}   

Would you agree?
I'll think about a constant though.

----

Now that I'm playing around with the DesktopCitizen I can see again a behavior that I already noticed  before but  didn't care much about it:
If you start the application and just move the window around, then close the window and open it  again only the size is correct, not the position.
It  works as it should, only if you first move the window and then resize it.

Both events:

stage.nativeWindow.addEventListener( NativeWindowBoundsEvent.RESIZE, onResize );
stage.nativeWindow.addEventListener( NativeWindowBoundsEvent.MOVE, onResize );

are handled in
protected function onResize( event:Event ):void

Tracing the rect.x and rect.y for both event types shows that RESIZE overwrites the x and y due to  MOVE with different values.
In DesktopCitizen.xml the values of x and y change only after RESIZE.

So if you only have
stage.nativeWindow.addEventListener( NativeWindowBoundsEvent.MOVE, onResize );
and look at the  DesktopCitizen.xml  the values of  x and y don't change at all after closing.
I know, I'm not explaining it well...

Maybe a nativewindow bug ?


Thank you.

EDIT:
I did this:

protected function onResize( event:NativeWindowBoundsEvent ):void
{
   if ( windowMetricsProxy.displayState == NativeWindowDisplayState.NORMAL )
   windowMetricsProxy.bounds =  event.afterBounds ;
  sendNotification( WINDOW_SHOW );
}

and now it works on MOVE too.
« Last Edit: March 22, 2009, 09:02:07 by Ondina » Logged

~ Ondina ~
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #7 on: March 24, 2009, 07:44:12 »

Excellent catch on the move without resize bug!

And on the constant for the enable flag, I see no reason for it with your new scheme. That's far cleaner. When you're finished, if you could send me a patch, I'll apply it to the codebase and rev the utility. I'm using it on a current project so I can try it out right away. I'll test this buggy behavior on the move without resize tonight.

Thanks,
-=Cliff>
Logged
Ondina
Sr. Member
****
Posts: 86


View Profile Email
« Reply #8 on: March 24, 2009, 10:26:02 »

Thank you Cliff  for your approval  :)

I don't know how to send a patch or what you meant by it, but I'll attach the application that contains all the changes.

The DesktopCitizenTest.zip  file is 32k.

The library files for DesktopCitizen are under src.org

You can play around with it and see what could be done better.

I don't know if you can  see any use for the Event.USER_IDLE and Event.USER_PRESENT.
I need them in my current project, but I can handle that without DesktopCitizen in case you don't want them there.

Ondina
Logged

~ Ondina ~
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #9 on: March 24, 2009, 04:48:03 »

In FlexBuilder with the svn plugin if you have something checked out of a repository you don't have write access to, you can create a 'patch' which essentially is the changes you would otherwise check in. Most large software projects work on this principle, with patches being submitted by users, then a committer applies the patch to their checked out copy, test it and if approved, commits the changes. No worries though, you can just zip it all up and mail it to me. I do most of my forum maintenance on my Blackberry catch as catch can, so unless an important submission shows up in my email where I can mark it for follow up, it runs the risk of falling between the cracks.

For these user events, I'm not sure they conceptually fit with the utility reallyunless you see a good reason for it.

Thanks,
-=Cliff>
Logged
Ondina
Sr. Member
****
Posts: 86


View Profile Email
« Reply #10 on: March 25, 2009, 12:04:34 »

In FlexBuilder with the svn plugin if you have something checked out of a repository you don't have write access to, you can create a 'patch' which essentially is the changes you would otherwise check in. Most large software projects work on this principle ...

Aha, ok. 
I'm not part of a large software team, so I've  never had to use it until now. I'll take a look at it.

You can just zip it all up and mail it to me.

The zip file was in the attachment of my previous post, but I'll mail it to you if you can't download it from there.

Thank you for  your time and your assistance :)

Ondina
Logged

~ Ondina ~
Jason MacDonald
Sr. Member
****
Posts: 243


View Profile Email
« Reply #11 on: March 25, 2009, 06:07:54 »

I'm not part of a large software team, so I've  never had to use it until now. I'll take a look at it.

Even as a single developer, I use SVN just so I have the ability to roll back changes. I often go down a road of development that I later decide isn't working out. And being able to roll back my changes to the point where I started is a blessing. :)
Logged
Ondina
Sr. Member
****
Posts: 86


View Profile Email
« Reply #12 on: March 25, 2009, 06:19:11 »

Yeah, good point Jason. I'll follow your advice and make SVN into a habit.
Thank you:)
Logged

~ Ondina ~
Ondina
Sr. Member
****
Posts: 86


View Profile Email
« Reply #13 on: March 27, 2009, 08:20:50 »

Hey Cliff

DesktopCitizen is addictive.

Now I'm wasting spending my time with a behavior I would like to catch:
I want to relocate the window in case the user moves it off screen.

Something like this:

private var mainScreen:Screen = Screen.mainScreen;
private var screenBounds:Rectangle = mainScreen.bounds;
protected function onResize( event:NativeWindowBoundsEvent ):void
{
   var windowRectangle:Rectangle=event.afterBounds;
   stage.nativeWindow.bounds = windowRectangle;

   if(event.afterBounds.left<screenBounds.left ){
      windowRectangle.offset( -event.afterBounds.left, 0 );
   }
   if( event.afterBounds.top<screenBounds.top){
      windowRectangle.offset( 0, -event.afterBounds.top );
   }
...



Have you got the time to look at the files I attached in a previous post and also sent per email? Just curious, nothing more.

Ondina
Logged

~ Ondina ~
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #14 on: March 27, 2009, 10:19:38 »

Hi Ondina,

Unfortunately, I'm onsite with a client and haven't had much time to do more than answer forum questions from my phone when a second arises, and evening bandwidth has dropped to zero since I'm preparing a presentation and a product against a late april deadline. I do anticipate getting into it, sinxe the product uses the util, but I'm flying home and back this weekend. Probably next week sometime.

On the moving offscreen part, be careful, the user may have two monitors. At home, I do, and the utility is able to remember which screen. But it would be quite nice to be able to detect if the other monitor is off, as it is when I disconnect my laptop and take it on the road. I'm not sure if AIR knows how many screens you have. It just looks like one big desktop. So if you do the math and determine the window is off the current desktop bounds, yes, itd be nice to perhaps center it within the current bounds.

-=Cliff>
Logged
Pages: [1] 2
Print