Windows and Dialogs

A running SiteFusion application always has at least one window open. This root window is an object of the class XULWindow and is opened automatically and made available through the Application::$window property. To influence the characteristics of this root window, you can set some properties in the Application class definition:
  • Application::$alwaysLowered - boolean indicating whether the window should always be under the other windows. Defaults to FALSE.
  • Application::$alwaysRaised - boolean indicating whether the window should always be on top of the other windows. Defaults to FALSE.
  • Application::$centerscreen - set to TRUE to have the window open in the center of the screen. Defaults to FALSE.
  • Application::$resizable - whether the user should be able to resize the window. Defaults to TRUE.
  • Application::$width - default width of the window (integer). Defaults to NULL, which makes the window autosize to its contents. Note that both width and height need to be set to force a size.
  • Application::$height - default height of the window (integer). Defaults to NULL, which makes the window autosize to its contents. Note that both width and height need to be set to force a size.
The properties Application::$alwaysLowered and Application::$alwaysRaised might not always result in the desired behavior, this seems to be dependent on the platform specific implementation of XULRunner.

In an empty application, the root window is the only registered node. Any nodes added as its children will appear inside it, as demonstrated in earlier tutorials. Windows in XUL and SiteFusion are just another kind of nodes. In the case of windows, being registered (e.g. becoming a child of another node) makes them open and initialize. Likewise, when windows are closed, either by the user or by the server process, the node is unregistered and removed from its parent childset. Window classes, like the Application class, have an init() function that is called when the window has been created on the client side. The default class provides a simple init function, but when writing extending classes, this is the function to override and use to construct the inner content of the window.

Other windows

SiteFusion distinguishes between two additional types of windows: XULChildWindow and XULDialog. They both behave largely the same way, but may be rendered differently depending on the platform. XULDialog extends XULChildWindow, so all options available to XULChildWindow also apply to XULDialog. Additionally, a dialog will display a set of buttons on the bottom (accept and cancel buttons by default), which are bound to specific events enabling you to react to those buttons appropriately. A dialog is mostly used to gather information from the user when requested by another part of the application, while a child window often represents a more independent part of an application. Dialogs and child windows can be constructed inline, or extended by a new class implementing the specific desired functionality of that window. Like the root window, the childwindow and thereby its extending class supports several options that can be set on the object or class definition:
  • XULChildWindow::$alwaysLowered - boolean indicating whether the window/dialog should always be under the other windows. Defaults to FALSE.
  • XULChildWindow::$alwaysRaised - boolean indicating whether the window/dialog should always be on top of the other windows. Defaults to FALSE.
  • XULChildWindow::$centerscreen - set to TRUE to have the window/dialog open in the center of the screen, or FALSE to have it open on a position relative to its parent window. Defaults to TRUE.
  • XULChildWindow::$dependent - set to TRUE to make the window/dialog dependent on its parent window. That means that if the parent window moves, the child moves with it. Defaults to TRUE.
  • XULChildWindow::$dialog - determines whether the look of the window should match a native dialog. Defaults to FALSE for child windows and to TRUE for dialogs.
  • XULChildWindow::$modal - a modal window/dialog prevents interaction with other windows until it is closed. This is useful if the application needs a certain task cleared or an answer supplied before it can continue. Defaults to FALSE.
  • XULChildWindow::$resizable - set to TRUE to enable resizing of the window/dialog. Defaults to TRUE for child windows and to FALSE for dialogs.
  • XULChildWindow::$title - set the title of the window/dialog (string)
The size of these windows can be set through the XULBasicWindow::size() method.

Inline construction

When constructing a dialog or child window inline, behavior is much like any other node:

<?php

function authorizeLogin$args$user$pass ) {
    return 
TRUE;
}

function 
getApplication$args ) {
    return 
'SFDialogDemo';
}

class 
SFDialogDemo extends Application
{
    public function 
init$event ) {
        
$this->window->addChild(
            
$btDialog = new XULButton'Open Dialog' ),
            
$btChildWindow = new XULButton'Open Window' )
        );

        
$btDialog->setEventHandler'command'$this'openDialog' );
        
$btChildWindow->setEventHandler'command'$this
                            
'openChildWindow' );
    }
    
    public function 
openDialog$event ) {
        
$this->window->addChild(
            
$dialog = new XULDialog'Nice Dialog',
                new 
XULLabel'This is a nice dialog indeed' )
            )
        );
    }

    public function 
openChildWindow$event ) {
        
$this->window->addChild(
            
$cwin = new XULChildWindow'Some Window',
                new 
XULLabel'Hi there' )
            )
        );
    }
}



This method of construction is most suitable for small, relatively unimportant dialogs and windows. It allows you to put together the contents of the window on the fly.

Note: Unlike other nodes, child nodes added to a dialog or childwindow node right after or during their construction, as in the above example, are not registered until the next event cycle. This is because windows need to send an 'initialized' event before their childnodes can be registered. Childnode methods that require a node to be registered (like Node::setAttribute() or Node::setEvent()) can be called from an event handler for this event.

<?php

function authorizeLogin$args$user$pass ) {
  return 
TRUE;
}

function 
getApplication$args ) {
  return 
'SFDialogEventExample';
}

class 
SFDialogEventExample extends Application
{
  public function 
init$event ) {
    
$this->window->addChild(
      
$dialog = new XULDialog'My Dialog',
        
$checkbox = new XULCheckBox'Check me' )
      )
    );
    
$dialog->checkbox $checkbox;
    
$dialog->setEventHandler'initialized',
          
$this'initDialog' );
  }

  public function 
initDialog$e ) {
    
$e->sourceObject->checkbox->setEvent'command'MSG_SEND,
          
$this'handleCheckbox'$e->sourceObject->checkbox );
  }
  
  public function 
handleCheckbox$e ) {
    
$this->window->alert(
      
$e->sourceObject->checked 
        
"It's on!" "It's off..."
    
);
  }
}


Writing an extending class

If you require a little more functionality, you'll want to write a separate class for the window or dialog. This allows you to have a self-contained piece of code, governing both the layout and the event handling and other functionality of the window or dialog. This also allows you to keep the rest of the application clean and keep all code directly concerning the dialog within the dialog class:

<?php

function authorizeLogin$args$user$pass ) {
  return 
TRUE;
}

function 
getApplication$args ) {
  return 
'SFDialogClassExample';
}

class 
SFDialogClassExample extends Application
{
  public function 
init$event ) {
    
$this->window->addChild(
      
$this->textbox = new XULTextBox,
      
$button = new XULButton'Do something' )
    );
    
$button->setEvent'command'MSG_SEND$this,
              
'openDialog'$this->textbox );
  }

  public function 
openDialog$event ) {
    
$this->window->addChild(
      new 
DemoDialog$this->textbox->value )
    );
  }
}

class 
DemoDialog extends XULDialog
{
  public function 
__construct$text ) {
    
$this->originalText $text;
    
$this->title 'Sure?';
  }
  
  public function 
init() {
    
$this->addChild(
      new 
XULLabel'Want to edit this?' ),
      
$this->textbox = new XULTextBox
    
);
    
$this->textbox->value$this->originalText );
    
$this->setEvent'accept'MSG_SEND$this,
              
'onAccept'$this->textbox );
  }

  public function 
onAccept$event ) {
    
$newText $this->textbox->value();
    
$this->rootApplication->textbox->value$newText );
  }
}


Dialog events

Windows and dialogs fire several events which can be used to bind functionality to. Both fire the 'initialized' event, which is handled internally leading to the default init() function being called. Both also fire the 'close' event when the close button the titlebar is clicked. You can use this event to do some cleanup for example, or to prevent the window from actually closing if it is not supposed to. This is done by calling the XULBasicWindow::preventClose() method. Dialogs fire several other events that relate to the specific system buttons that this class provides. By default, a dialog will have the OK and Cancel buttons, usually localized to the system language. These buttons fire the 'accept' and 'cancel' events respectively. The full set of buttons a XUL dialog can display and their correspondingly named events are:
  • accept - the OK button
  • cancel - the Cancel button
  • help - a button to provide help in an operating system consistent way
  • disclosure - a button to show more information. Visual representation may differ across systems
  • extra1 - a generic extra button
  • extra2 - a second generic extra button
Setting the buttons to be displayed is done by setting the XULDialog::$buttons property to a comma-separated string containing any of the above button names. For example, setting $dialog->buttons = 'accept,cancel,disclosure'; will show the accept, cancel and disclosure buttons. All buttons except the extra1 and extra2 buttons have default labels, determined by the localization settings of XULRunner. These can be changed however, through the following set of methods:

Window references

All registered nodes hold references to their root and host windows. The root window is contained in the Node::$rootWindow property. The property Node::$hostWindow points to the window that contains the node.

<?php

function authorizeLogin$args$user$pass ) {
  return 
TRUE;
}

function 
getApplication$args ) {
  return 
'SFWindowReferenceExample';
}

class 
SFWindowReferenceExample extends Application
{
  public 
$width 400;
  public 
$height 300;
  
  public function 
init$event ) {
    
$this->window->addChild(
      new 
AllknowingLabel,
      new 
DemoDialog
    
);
  }
}

class 
DemoDialog extends XULDialog
{
  public function 
init() {
    
$this->addChild( new AllknowingLabel );
  }
}

class 
AllknowingLabel extends XULLabel
{
  public function 
__construct$label NULL$style NULL ) {
    
parent::__construct$label$style );
    
$this->setEventHandler'onAfterAttach'$this'setLabel' );
  }

  public function 
setLabel$event ) {
    if( 
$this->hostWindow === $this->rootWindow )
      
$this->value"I'm in the root window" );
    else
      
$this->value"I'm in another window" );
  }
}


Although not required, it is good practice to always have windows be the parents of others windows. Adding a window node to a non-window node's child collection will work, but if the node is removed, the window is closed. When it comes to dependent windows (usually dialogs), you'll usually want them to close when their parent window closes. Independent child windows can be added to the root window to keep them open as long as the application runs.




Comment on this tutorial
Name:
Email:
 
Copy the code: