Window System

Window system of NeuroKernel is designed as part of the kernel. An application window is allocated for each application by the window manager module. This window is destroyed along with the task information and resources when the application exits. The window system of NeuroKernel is as advanced as X Window System. There are various window types available to developers. The default theme is called Karia, and it is designed to give both a vintage and modern look.

1. Window Manager

Window manager is responsible with creating, destroying and managing windows. It also manages NeuroKernel's powerful plugin system. When a task is created it is automatically assigned a task context which also includes a top level window. User interface of an application will be rendered only if the toplevel window is made visible or painted. Applications must always extend NApplication class. Window manager is a sub module of kernel and is not a separate task.

1.1 Ordering

Windows are ordered by their parent and type. Child windows are always rendered on top of their parent first. Dialog windows and tool windows will always remain on top of their parent window. Some windows may be made to ignore window organizer and may float on top of all other application windows. Only kernel, display manager and desktop manager can create these runaway windows.

1.2 Resize

Resizing a window can be done in multiple ways. It can be resized interactively by the user if the resize decorations are available on the window, or it can be resized from the window menu which is opened with the right click when on window title. The keyboard shortcut key for the window menu is shift+ctrl+A. It is also possible to use setBounds or setSize methods on a NWindow to set the size of the window programmatically.

1.3 Move

Moving a window can be done in multiple ways. It can be moved interactively by the user using the title(or move) decoration if available on the window, or it can be moved from the window menu which is opened with the right click when on window title. The keyboard shortcut key for the window menu is shift+ctrl+A. It is also possible to use setBounds or setLocation methods on a NWindow to set the size of the window programmatically.

1.4 Minimize

Minimizing a window will hide the window from the view. If supported by the desktop manager, an icon will be shown indicating that it is minimized. It is possible to bring up the window list and deiconify a window. The shortcut key for the the window list is shift+ctrl+W. It is also possible to bring the window list using the system manager. Window can be interactively minimized from the window decoration if it is available. Window menu can also be used to minimize a window.

1.5 Maximize

Maximizing window will resize a window to cover the entire desktop view. It can be down interactively using the allocated decoration if available. Window may be restored to its previous size by repressing the maximize button which will change its image to indicate the current state of the window. It is also possible to maximize a window only vertically or horizontally by double pressing the resize bars if available. Double clicking the title bar will also maximize/restore the window. Window menu can always be used as well.

1.6 Close

Closing window is done by pressing the close button decoration of the window. Window menu can also be used for this operation. Developers can choose a window closing policy depending on the use case.

1.7 Pinning

Pinning a window is only available in NeuroKernel rootless mode which runs embedded in another web page. When a window is pinned it will keep its position on the screen even if the page scrolls. A window can be pinned or unpinned from the window menu or using the NDocumentWindow object which is only available to a desktop manager application in rootless mode.

1.8 Window Spaces

There are nine window spaces for users to layout their windows in. A window space is actually a desktop window which means user has 9 different desktop window to choose from. Window space of window can be selected by the window menu, desktop menu or by pressing Ctrl+F8 (or Cmd+F8).

1.9 Window Menu

Each window has a window menu that can be triggered by the user by pressing right mouse button on the window moving component which by default is the title bar. A short cut key (shift+ctrl+A) combination can also bring the window menu up. Applications are allowed to add new items to the window menu if needed.

import com.neurokernel.client.*;
 
public class WindowMenu extends NApplication {
    @Override
    public void main(int argc, String[] argv) {
        NFrame mainFrame=getMainFrame();
 
        NMenu menu = toplevel.getWindowMenu();
        NMenuCell properties = new NMenuCell(menu, "Properties...", true);
        menu.getColumn().moveRow(properties, 5);
        menu.validateContent();
        menu.getColumn().addListener(new NActionListener() {
            private static final long serialVersionUID = 1L;
            @Override
            public void onAction(NEvent e) {
                int row=e.getRow();
                if (row == 5) {
                    getConsole().print("Window Properties Clicked");
                }  
            }
        });
 
        mainFrame.setTitle("Window Menu");
        mainFrame.setBounds(20,20,300,300);
        mainFrame.setVisible(true);
    }
}

2. Desktop Window

Desktop window is specially treated by the window manager. It never gets any decorations and always made fullscreen except when in document window. If there is no desktop manager to run, kernel takes over the as desktop management however no icons or anything similar will be shown. This can be observed by killing the desktop manager application, and rerunning it. It is similar how Explorer task works on Windows Operating System.

3. Application Window

When an application execution request reaches Kernel, the task processor module asks window manager to allocate an application main window. This top level window is the root to all other windows, dialogs or tool windows created by the application. Windows and controls are created in a tree hierarchy where the top level main window is the root of all. Destroying the main window means exiting the application entirely.

4. Normal Window

Normal windows are created by the application main window, being the top of the window hierarchy of an application. It is possible to use a normal window as the parent of another window.

import com.neurokernel.client.*;
import com.neurokernel.client.annotation.LoadResources;
import com.neurokernel.client.annotation.Source;
 
@LoadResources(
    resources = {
        @Source(value = "resources/banner.png", name = "banner")
    }
)
public class MyApplication extends NApplication {
    @Override
    public void main(int argc, String[] argv) {
       NFrame mainFrame=getMainFrame();
       mainFrame.setTitle("Frame Example");
       mainFrame.setBounds(20,20,300,300);
       mainFrame.setVisible(true);
 
       NFrame splashWindow = new NFrame(mainFrame);
       splashWindow.setDecorations(NWindow.DECOR_NONE);
       new NImageView(splashWindow, (NImage)getResource("banner"));
       splashWindow.setSize(250, 250);
       splashWindow.centerWindow()
       splashWindow.setVisible(true);
    }
}

5. Dialog Window

Dialog windows block event processing on their immediate parent. A dialog window can spawn another dialog window when necessary. Unlike other web applications, dialog windows in NeuroKernel are real dialogs that behaves like their desktop counterparts blocking only their parent window hierarchy instead of entire web page. Dialog windows cannot create a tool window. Default close operation of a dialog is hide-on-close.

import com.neurokernel.client.*;
import com.neurokernel.adapter.NActionListener;
 
public class DialogExample extends NApplication {
      NFrame mainFrame;
      AskQuestion question;
 
      @Override
      public void main(int argc, String[] argv) {
          mainFrame=getMainFrame();
          question=new AskQuestion(mainFrame);
 
          new NButton(mainFrame,"Hello!").addActionListener(new NActionListener() {
              @Override
              public void onAction(NEvent e) {
                  question.setVisible(true);
              }
          });
 
         question.addDialogListener(new NDialogListener() {
                @Override
                public void onOK(NEvent event) {
					NMessageDialog.showInfo(mainFrame,question.getUserName());
                }
          });
 
          mainFrame.setTitle("Hello There");
          mainFrame.show(20,20);
      }
 
      /**
       * Command Dialog Example
       */
      static class AskQuestion extends NCommandDialog {
          NTextField name;
 
          public AskQuestion(NWindow parent) {
              super(parent, "Enter Name", false);
              getContentPane().getLayout().setPadding(5, 0, 5, 0);
              name = new NTextField(content);
              name.setPromptText("Enter Your Name");
              getOKButton().getForm().addField(name);
              setSize(300, 80);
          }
 
          public String getUserName() {
          	return name.getText();
          }
      }
}

6. Tool Window

Tool windows are special windows that always remain on top of their immediate parent. Only main windows and normal windows can spawn tool windows. Tools windows can also be organized in themselves and can be made sticky or always-on-top. Sticky tool windows will retain their position relative to their parent.

import com.neurokernel.client.*;
 
public class MyApplication extends NApplication {
    @Override
    public void main(int argc, String[] argv) {
       NFrame mainFrame=getMainFrame();
       mainFrame.setTitle("Tool Frame Example");
       mainFrame.setBounds(20,20,300,300);
       mainFrame.setVisible(true);
 
       NToolFrame toolA = new NToolFrame(mainFrame, "Sticky");
       toolA.setWindowSticky(true);
       toolA.setBounds(30, 30, 250, 250);
       toolA.setVisible(true);
 
       NToolFrame toolB = new NToolFrame(mainFrame, "Always on Top");
       toolB.setAlwaysOnTop(true);
       toolB.setBounds(50, 50, 200, 200);
       toolB.setVisible(true);
    }
}

Menu windows are used for all popup menu purposes. An application can have any number of menus and nested menus. They are made hidden automatically by the system when an action happens on them. It is also possible to create menus using normal windows with no decorations, but their visibility should be handled by the application. Please note that Unregistered Remote Applications can not create windows with no decorations.

import com.neurokernel.client.*;
 
public class MenuExample extends NApplication {
      @Override
      public void main(int argc, String[] argv) {
          final NFrame mainFrame = getMainFrame();
          mainFrame.setFrameLayout(NFrameLayout.MENUBAR);
 
          NMenuBar menubar = new NMenuBar(mainFrame);
          NMenu menu = new NMenu(toplevel);
          new NMenuCell(menu, "Open");
          new NMenuCell(menu, "Exit").addSeparator();
          menubar.addMenu("File", menu);
 
          menu.getColumn().addListener(new IEventListener() {
               @Override
               public void onEvent(NEvent event) {
                  if (event.getEventType() == NEventTypes.ACTION) {
                      if (event.getRow() == 0) {
                         NMessageDialog.showInfo(mainFrame,"Open a File?");
                      } else {
                         exit();
                      }
                   }
               }
          });
 
          new NButton(mainFrame,"Hello").addActionListener(new NActionListener() {
              @Override
              public void onAction(NEvent e) {
                  NMessageDialog.showInfo(mainFrame,"Hello There!");
              }
          });
 
          mainFrame.setTitle("Menu Example");
          mainFrame.setBounds(20,20,200,200);
          mainFrame.setVisible(true);
      }
}

8. Document Window

Document window can only be created when in rootless mode. Rootless mode is a special mode where NeuroKernel can be embedded in a normal web page. The desktop window is not made visible on this mode to make the web page operational. In this mode, desktop window can spawn any kind of window, and it can also embed windows inside DIV elements, and the size of a window is automatically updated when the size of the parent DIV element changes. This makes creative mashups with NeuroKernel possible. The code segment below shows an example use of document window in a desktop manager implementation.

final NFrame rootlessTest=new NFrame(getMainFrame());
new NButton(rootlessTest,"test").addListener(new IEventListener() {
    boolean pinned;
    @Override
    public void onEvent(NEvent e) {
        pinned=!pinned;
        rootlessTest.pinToDocument(pinned);
        NDocumentWindow doc=getRootDocument();
        doc.setBackground(NColor.BLUE);
        doc.scrollTo(2000, 0, NAnimation.Easing.EXPONENTIAL_IN);
    }
}, NEventTypes.ACTION);
 
rootlessTest.setSize(200, 150);
rootlessTest.setVisible(true);
 
NWindow window=getRootDocument().createWindow(htmlRenderer.getElement("staticpanel"));
new NComboBox(window,"test").getColumn().importData("Hello","World");
window.setSize(200, 200);
window.setVisible(true);

In the second part of the code, after making the rootlessTest frame visible, a window is created inside a DIV element named staticpanel.

9. Layout Windows

Layout windows are not managed by the window manager. They are managed by application container layout itself. Internal windows are rendered by the same rendering engine as normal windows, and they can also be themed programmatically by the look and feel manager.

9.1 Panel Window

Panel windows are federated window contexts that live in the layout of their parent container. It has its own control hierarchy, keyboard handling and scrolling. They may be useful when there are too many controls on a window that may slow down the event processing such as tables or lists. NScrollPane directly inherits NPanelWindow, and used as a scrollable tree view in the example below.

import com.neurokernel.client.*;
 
public class ScrollPane extends NApplication {
    @Override
    public void main(int argc, String[] argv) {
        NFrame mainFrame=getMainFrame();
 
        //Scroll Pane contains Panel Window
        NTreeView tree = new NTreeView(new NScrollPane(mainFrame));
        NTreeCell t1 = new NTreeCell(null, "Node 1");
        t1.setChecked(false);
        NTreeCell t2 = new NTreeCell(null, "Node 2");
        NTreeCell t3 = new NTreeCell(t2, "Node 3");
        t3.setChecked(false);
        NTreeCell t4 = new NTreeCell(t1, "Node 4");
        NTreeCell t5 = new NTreeCell(t4, "Node 5");
        tree.addRows(new NCell[] { t2, t3, new NTreeCell(t3, "Node 6"));
        tree.addRows(new NTreeCell[] { t1, new NTreeCell(t1, "Node 7"), t4,
                                     new NTreeCell(t4, "Node 8"), t5,
                                     new NTreeCell(t5, "Node 9"), });
 
       mainFrame.setTitle("ScrollPane Example");
       mainFrame.setBounds(20,20,300,300);
       mainFrame.setVisible(true);
    }
}

9.2 Internal Window

When using very large screens, an MDI type user interface may help consolidate the concentration on the application itself. It may be hard to control all the spawned windows on a large screen. There are other use cases where they can be very useful as well. They are basically decorated and managed as normal windows but live in a parent desktop panel. It is possible to change the default decorations programmatically like normal windows.

import com.neurokernel.client.*;
 
public class MDIExample extends NApplication {
    @Override
    public void main(int argc, String[] argv) {
        NFrame mainFrame=getMainFrame();
 
        NDesktopPane pane=new NDesktopPane(mainFrame);
 
        NInternalFrame frameA=new NInternalFrame(pane);
        new NButton(frameA,"Hello");
        frameA.setBounds(5,5,200,200);
 
        NInternalFrame frameB=new NInternalFrame(pane);
        new NButton(frameB,"World");
        frameB.setBounds(15,15,200,200);
 
        mainFrame.setTitle("MDI Example");
        mainFrame.setBounds(20,20,400,400);
        mainFrame.setVisible(true);
    }
}

9.3 Window Accessibility

Windows accessibility is largely done with keyboard and window menu. It is possible to move, resize or focus windows using using keyboard. Dialogs will be made hidden or disposed by pressing ESC key for example. Please see 'User's Guide' for full list shortcut keys and details of the window menu.