In order to add a new namespace into the ConsoleOne shell, you must create a new class and implement the NamespaceSnapin interface. The NamespaceSnapin interface extends the Snapin interface, from which the following four methods are derived. These methods must be implemented in your new namespace snap-in.
These four Snapin interface methods are described in detail in Required Methods to Implement. In addition to implementing these methods in your new class, you must also register your snap-ins to the ConsoleOne shell by implementing the Registration interface. For a complete description of snap-in registration see Registering Your Snap-Ins.
The NamespaceSnapin interface defines the following five methods, which are used to describe the new namespace.
The following paragraphs describe these methods defined by the NamespaceSnapin interface.
The getUniqueID() method is used to get the unique identifier or name of the namespace. You must return a name that the shell will use for the namespace being described. The unique namespace identifier is the key used to register snap-ins that will operate against this namespace. It is suggested that you return, as the uniqueID string, the package name and class implemented in the namespace snap-in. An example of getUniqueID(), as used in ConsoleOne, is as follows:
public String getUniqueID()
{
return "com.novell.sample.snapins.FileSystemNamespace";
}
The getFullName() method is used to return the full name of the ObjectEntry for which the full name is desired. The full name should represent a unique name in the namespace. Following is an example program listing for this method.
public abstract String getFullName(ObjectEntry entry)
{
return entry.getName();
}
The getObjectEntry() method is used to return the ObjectEntry associated with a unique string. If no ObjectEntry is found an exception is thrown. Following is an example program listing for this method.
public ObjectEntry getObjectEntry(String name) throws ObjectNotFoundException
{
return makeObjectEntry(name, null);
}
The getInitialObjectEntries() method is used to return the root ObjectEntry array. Null can be returned if there are no root object entries in the namespace. Following is an example program listing for this method.
public ObjectEntry[] getInitialObjectEntries()
{
ObjectEntry[] roots = new ObjectEntry[1];
try
{
roots[0] = makeObjectEntry(File.separator, null);
return roots;
}
catch(ObjectNotFoundException e)
{
return null;
}
}
The getChildren() method is used to obtain an enumeration of subordinate objects (list of children from the current namespace) that the shell will use for the namespace being described. The parameter passed is the parent object in the current namespace from which a list of children can be obtained. Following is an example program listing of the getChildren() method.
public ObjectEntryEnumeration getChildren(ObjectEntry parent) throws NotAContainerException
{
File file = new File(parent.getName());
if(!file.isDirectory())
{
throw new NotAContainerException();
}
String [] children = file.list();
if (children != null)
{
return new FileEnumeration(children, parent, this);
}
return null;
}
In association with the getChildren method, you can implement the ObjectEntryEnumeration interface or use the DefaultObjectEntryEnumeration class. This class is a convenience helper class for creating ObjectEntryEnumerations. The DefaultObjectEntryEnumerations class converts an ObjectEntry array, Vector or Enumeration to an ObjectEntryEnumeration that can be returned from the getChildren() methods of the NamespaceSnapin or ExtendChildrenSnapin interfaces.
The following code shows an implementation of ObjectEntryEnumeration.
public class FileEnumeration() implements ObjectEntryEnumeration
{
// field data
private ObjectEntry [] m_entries;
private int m_index;
// class constructor
public FileEnumeration(String[] files,
ObjectEntry parent,
FileSystemNamespace namespace)
{
// defines the m_entries array and setup m_index
m_entries = new ObjectEntry[files.length]; //same size as files[]
m_index = 0;
// fill in m_entries array
for(int i = 0; i < files.length; i++)}
{
m_entries[i] = namespace.makeObjectEntry(files[i], parent);
}
// sort the entries using custom sorter routine
sorter(m_entries, entries.length - 1);
}
// implementation of the objectEntryEnumeration interface
// returns the next ObjectEntry of the enumeration
public objectEntry next()
{
if(hasMoreElements())
{
return m_entries[m_index++];
}
else
{
throw new NoSuchElementException(); // no more elements
}
}
// implementation of the Enumeration interface, which is
// extended by the ObjectEntryEnumeration
public boolean hasMoreElements()
{
return m_index < m_entries.length;
}
public Object nextElement()
{
return next();
}
}
At a minimum, a snap-in collection for a new namespace needs to provide the names and icons that should be displayed for object entries provided by the new namespace, unless the defaults are to be used. You do not have to write your own view if you just want to show the list of children in a container. If all you want is a basic list of the subordinate objects of the selected container, add an extra RegistrationItem object into the array returned by the namespace’s getRegistration() method that registers the console view for use on the new namespace. For example, to register the console view for a new namespace, you can use the following:
new RegistrationItem(new NamespaceTreeObjectsScope(Shell.SNAPIN_VIEW,
<namespace unique id to register console view against>),
"com.novell.application.console.consolesnapins.ConsoleView")
To add a new namespace to ConsoleOne, including a console view and the names and icons for objects, use the following steps:
ConsoleOne namespaces work only with the model, which provides for a default name and image for namespace items. In order to override the default display name and image for items in a new namespace, you must create a new class by implementing both the DisplayIconSnapin and DisplayNameSnapin interfaces. These two interfaces extend the Snapin interface, from which the following four methods are derived. These methods must be implemented in your new class.
These four Snapin interface methods are described in detail in Required Methods to Implement. In addition to implementing these methods in your new class, you must also register your snap-ins to the ConsoleOne shell by implementing the Registration interface. For a complete description of snap-in registration see Registering Your Snap-Ins.
The new snap-in class that implements the DisplayIconSnapin and DisplayNameSnapin interfaces provides the text and image that will show up in the object browser tree and the view for namespace items.
The DisplayIconSnapin interface, used to provide the icon (image) for a specified ObjectEntry, defines the following three methods.
As noted above, two different forms of the getDisplayIcon() method are defined, the first returning the snap-in icon associated with the specified ObjectEntry parameter (entry). A null can be returned when there is no icon available, in which case a default icon is returned for the specified entry type only if no other registered snap-in has been defined that provides an icon for that type of entry. Otherwise, a search of all available snap-ins is conducted, and the first snap-in that provides an icon for the specified entry is used to return the icon.
Below is an example of using the ObjectEntry parameter.
public Icon getDisplayIcon(ObjectEntry entry)
{
return getDisplayIcon(entry.getObjectType().getNamespace().getUniqueID(),
entry.getObjectType().getName());
}
The second construct of the getDisplayIcon() method returns the icon associated with the ObjectType that has the same name as the String parameter type. A null can be returned when there is no icon available, in which case a default icon is returned for the specified entry type only if no other registered snap-in has been defined that provides an icon for that type of entry. Otherwise, a search of all available snap-ins is conducted, and the first snap-in that provides an icon for the specified entry is used to return the icon.
An example of using the ObjectType parameter is as follows:
public Icon getDisplayIcon(String namespace, String type)
{
Icon icon = (Icon) icons.get(type);
if(icon == null)
{
Image i = null;
String path = "/com/novell/sample/snapins/filesystem/images/";
path += type + ".gif";
URL url = getClass().getResource(path);
if(url != null)
{
i = Toolkit.getDefaultToolkit().getImage(url);
icon = new ImageIcon(i);
icons.put(type, icon);
}
else
{
System.err.println("Image loading URL is null in
ZipNamespaceDisplay::getDisplayIcon");
}
}
return icon;
}
The other method, doesIconChangePerEntry(), is used to determine if the image can change depending on the ObjectEntry of the given type, or if the snap-in will always return the same image for a particular ObjectType. Return true if the image can change depending on the ObjectEntry of the given type. If the snap-in always returns the same image for a particular ObjectType, this method should return false. This way ConsoleOne can cache the image, when possible, and use the same image for all objects of the given type. Here is an example implementation.
public boolean doesIconChangePerEntry(ObjectType type)
}
return false;
}
The DisplayNameSnapin interface, used to provide the display name for a specified ObjectEntry, defines two forms of the getDisplayName() method.
When using getDisplayName() with the ObjectEntry parameter (entry), you must return the display name that the shell will use to display the specified ObjectEntry in the tree or view. The name of the object is displayed next to an icon (display image) representing the object. A null can be returned when there is no name available, in which case a default name is returned for the specified entry type only if no other registered snap-in has been defined that provides a name for that type of entry. Otherwise, a search of all available snap-ins is conducted, and the first snap-in that provides a name for the specified entry is used to return the name.
Below is an example of the implementation of this method.
public String getDisplayName(ObjectEntry entry)
{
String name = entry.getName();
if(name.equals(""))
{
return "Invalid Entry";
}
int slash = name.lastIndexOf(File.separator);
if (slash > -1)
{
name = name.substring(slash + 1);
}
if(name.equals(""))
{
return "<Root>";
}
return name;
}
}
When using getDisplayName() with the two String parameters you must return the localized display name of the passed in object type. A null can be returned when there is no name available, in which case a default name is returned for the specified entry type only if no other registered snap-in has been defined that provides a name for that type of entry. Otherwise, a search of all available snap-ins is conducted, and the first snap-in that provides a name for the specified entry is used to return the name.
An example of the implementation of this method is shown below.
public String getDisplayName(String namespace, String type)
{
return type;
}
Use the following steps to display namespace information when you add a new namespace to the ConsoleOne shell.
Sample File System Namespace Display Program
The right panel in the ConsoleOne shell is referred to as the View. When an ObjectEntry is selected in the left panel tree, the shell examines the set of participating snap-ins to obtain a list of views that participate with that ObjectEntry. The view menu then displays a list of views in the form of Radio Menu Items.
ConsoleOne provides a default view which is made available to every namespace. This default view displays in a list a name and an image for each object entry in a namespace. Below is the code snippet showing how to register the console list view. To use the default view, register the snap-in using the variable "Shell.CONSOLE_VIEW_CLASS_NAME" as the className parameter for the RegistrationItem class constructor, as shown below:
new RegistrationItem(new NamespaceTreeObjectsScope(Shell.SNAPIN_VIEW, <namespace unique id against which to register console view >), "Shell.CONSOLE_VIEW_CLASS_NAME")
If you do not provide a view for namespace objects and do not register your snap-in with the default console view provided by ConsoleOne, the namespace will not have any view registered to it.
You can add views for objects in an existing namespace by creating a new class in which the ViewSnapin interface is implemented. The ViewSnapin interface extends the Snapin interface from which the following four methods are derived. These methods must be implemented in the new view snap-in.
These four Snapin interface methods are described in detail in Required Methods to Implement. In addition to implementing these methods in your new class, you must also register your snap-ins to the ConsoleOne shell by implementing the Registration interface. For a complete description of snap-in registration see Registering Your Snap-Ins.
The ViewSnapin interface defines the following five methods, which are used to describe your new view. They are listed and discussed in the order usually implemented.
Because of some method dependencies, we suggest that you implement these methods in the following order:
The following paragraphs describe the methods defined by the ViewSnapin interface.
The getView() method returns context information (as a ViewSnapinContext object) about the state of the Object Browser window. The getObjectEntry() method of the ViewSnapinContext class returns the currently selected ObjectEntry, as a Component, in the Object Browser window for which a view is needed by the ConsoleOne shell.
The current Object Browser context is also stored in the InitSnapinInfo parameter supplied to the initSnapin() method during ViewSnapin initalization. A call to getContext() will return a valid ViewSnapinContext for that point of time. But the context can change between initialization and the call to the getView() method. Therefore, the context should be obtained from the ViewSnapinContext parameter supplied in the getView() method and not from the context provided during initialization.
The following sample code snippet shows how the getView() method can be implemented.
// Global variables set up in the initSnapin() method
// p - the panel where the children will be displayed
// shell - an instance of the ConsoleOne shell
public Component getView(ViewSnapinContext viewContext)
{
// Remove any existing Components from the panel.
p.removeAll();
// Get enumeration of the selected ObjectEntry’s children.
ObjectEntryEnumeration children = shell.getChildren(viewContext.getObjectEntry());
// For each child, add enumeration to the panel and set up a
// mouse listener.
while(children.hasMoreElements())
{
ObjectEntry child = children.next();
MyLabel node = new MyLabel(child);
node.addMouseListener(new MyMouseListener());
p.add(node);
}
// Return the reformatted panel.
return p;
}
The getUniqueID() method returns the unique, non-localized name of the view. It is the unique identifier for snap-ins to identify the view and to register against the view. In a view snap-in the getUniqueID() method is called before the initSnapin() method. Also, if a view is changed by ConsoleOne, the getViewMenuName() method is called before the initSnapin() method. Following is an implementation example.
public String getUniqueID()
{
return "com.novell.sample.snapins.filesystem.FilesystemListView";
}
The getViewMenuName() method returns the language- dependent translated (localized) name that will be used as the text in the view menu. Place an ampersand (&) before a character to specify that character as the mnemonic character.
public String getViewMenuName()
{
return "S&le Filesystem List View";
};
The setInactive() method provides a shell notification that the snap-in is inactive. The shell sends a notification that the view snap-in has become inactive and should dispose of resources. The c parameter is the Component containing the instance of the view that the shell passes to the snap-in.
Use the following steps to add a new view for containers in an existing namespace.
ConsoleOne can display a property book with pages containing attribute values for various types of namespace objects. The PropertyBook is a binder, which manages the PageSnapins that have been registered globally or for the various types of objects in the namespaces. The PageSnapins are actually responsible for displaying the user interface required to enter, edit and delete property values for a particular type of ObjectEntry. The PageSnapins communicate with the PropertyBook so that the appropriate buttons (OK, CANCEL, APPLY, CLOSE) can be properly enabled or disabled during the entry/editing process.
In order to allow developers to furnish property pages for their own object types, ConsoleOne provides the PropertyBook interface and the PageSnapin interface. As mentioned, property pages provide the user interface required to enter and maintain attribute values for namespace objects. A single property page can support more than one attribute. You can write a property page for the purpose of administering an attribute to an existing object or to add a new object. You can also present unified objects from separate data sources.
NOTE:The size of property pages is hardcoded to 640 X 480, and the getPreferredSize() and setPreferredSize() methods, which were available in early versions of ConsoleOne, have been removed.
This has a couple of implications. First, if ConsoleOne hosts a property page snap-in, the minimum screen resolution required for ConsoleOne will effectively be 800 X 600. Second, it is up to you to ensure that any controls you put on your property pages actually fit on the page.
Note also that there is currently a possible problem with hosting a JComboBox swing component on a property page.
The ConsoleOne Property Book implements a concept called multi-page tabs. This feature allows PageSnapin writers to place more than one property page on a single tab. This is a helpful feature because, like menus, it provides the ability to organize property pages under logical tab headings instead of simply including a new tab for every property page. Some property page writers have implemented this feature by placing a combo-box in the content area of a property page, but this causes confusion and difficulty in finding all the property pages. By placing a pop-up menu on the tab that implements multiple pages, the user is able to find property pages much easier.
Property Book pages are grouped together on the same tab if their TabIDs, as returned by the getTabID() method of the PageSnapins, are identical. You can allow other developers to add pages to a tab created by your PageSnapin by making its TabID known.
The PageSnapin interface extends the Snapin interface, from which the following four methods are derived. These methods must be implemented in your property page snap-in.
These four Snapin interface methods are described in detail in Required Methods to Implement. In addition to implementing these methods in your new class, you must also register your snap-ins to the ConsoleOne shell by implementing the Registration interface. For a complete description of snap-in registration see Registering Your Snap-Ins.
The following two methods are defined in the PropertyBook interface.
The setModified() method is discussed in Page Modify Sequence.
The setTitle() method can be called to set the title of the current property book as follows.
thePageHost.setTitle( title );
The PageSnapin interface defines the following methods, which must be implemented in your property page snap-in class.
The following subtopics describe how the PageSnapin and PropertyBook methods are used. The protocol between the PropertyBook and PageSnapin interface is presented in four main sequences.
When the user selects an object in some namespace and then chooses the Properties... menu item, the menu snap-in that implements the Properites... menu item determines which ObjectEntries have been selected and places them in an array. A call to the shell.showDetails() method with this array as a parameter starts the processs of bringing up the property book.
The property book provides services to page snap-ins through the PropertyBook interface. ConsoleOne instantiates a PropertyBook and places the ObjectEntry array and PropertyBook reference in a PageSnapinContext object. Page snap-ins obtain a reference to the PropertyBook interface from the PageSnapinContext class when the initSnapin() method is called. A PageSnapinContext object is used by PageSnapins to determine which ObjectEntries are to have their properties edited. This object is passed to the PageSnapin on initialization through the InitSnapinInfo parameter to the initSnapin() method. The PageSnapinContext object can be retrieved from the InitSnapinInfo parameter by making a call to the getContext() method. The getObjectEntries() method of the PageSnapinContext class retrieves the ObjectEntry array from the context. The getPropertyBook() method of the PageSnapinContext class retrieves the reference to the PropertyBook from the context. Using this reference, the set of registered PageSnapin(s) can tell the PropertyBook when attribute values have changed so the appropriate PropertyBook buttons (OK, CANCEL, APPLY, CLOSE) can be enabled or disabled. Also, using the information in the PageSnapinContext, each PageSnapin creates a property page in the PropertyBook window. The number of pages displayed is determined by the number of PageSnapins registered for the namespace object type specified in the ObjectEntry array.
The following sample code snippet shows how a reference to the PropertyBook is obtained at the time PageSnapins are initialized.
public boolean initSnapin(InitSnapinInfo info)
{
shell = info.getShell;
type = info.getSnapinType;
context = (PageSnapin(context) info.getSnapinContext();
PropertyBook = context.getPropertyBook();
Objects = context.getObjects();
.
.
.
return true;
}
After the PropertyBook has loaded and initialized all page snap-ins and their tabs are shown, it calls each of their getPage() methods to obtain a user interface for their specific page.
The getPage() method retrieves the java.awt.Component associated with the current PageSnapin. Only a java.awt.Panel should be returned. This method is guaranteed to be called only once. At initialization, the PropertyBook calls the getPage() method to obtain a reference to the actual Panel for the given PageSnapin. You can extend Panel directly and return this reference or define a local Panel variable to implement the actual Panel.
The Panel sent to the PropertyBook by the getPage( ) method will normally be derived from java.awt.Container, so it can contain any combination of java.awt.Component objects that the developer wants to use in the user interface (such as, buttons, text fields, lists, and so forth). This method can be implemented as follows:
public Component getPage()
{
return this;
}
The getTabID() method returns a globally unique, language-independent identifier (TabID) for the tab folder where the current page is to be placed. This TabID can be any globally unique string. If a tab with the specified TabID exists, the page will extend the tab by converting it to a multi-page tab and adding the menu name to the tab’s dropdown menu. If no tab with the specified TabID exists, the PropertyBook will create a new tab folder and will use the display name obtained from the getTabName() method. The tab page is then added to this new folder.
public String getTabID()
{
return "com.novell.sample.snapins.filesystem.fileinfo";
}
The getTabName() method returns the language-dependent, translated display name for the tab where this page is to be placed. This string should be read from a resource file for the purposes of internationalization. This name will only be used when a new tab is being created, not when an existing tab is being extended. If this tab does not exist, the Property Book will use the string name for the tab name, otherwise it is ignored. The following code shows how the getTabName() call is made.
public String getTabName()
{
return "File Info";
}
The getMenuName() method returns the language-dependent menu name for the menu on multi-page tabs. The PropertyBook calls the getMenuName() method to determine the menu item name for this page if the tab is a multi-page tab. The menu item name is displayed in a pop-up menu whenever a user selects a multi-page tab. You can return NULL if the tab is not a multi-page tab and you are sure it will never be extended, that is, its TabID will never be published to the third-party development community.
The following code shows how the getMenuName() call is made.
public String getMenuName()
{
return "Rename";
}
The following two methods, hasHelp() and showHelp(), can be implemented to tell the PropertyBook if the Help button is enabled for your page or if you want to access the PropertyPage help.
The hasHelp() method is called to determine if the panel offers help. You should override this method and return true if you want to provide Help for your snap-in, and have the Help button enabled for your page. You should also override the showHelp() method.
public boolean hasHelp()
The showHelp() displays Help information when the hasHelp() method has returned true. This method is called when the user presses the Property Book Help button. To provide help for your snap-in, you must override the hasHelp() method to return true, then implement the showHelp() method.
public void showHelp()
{
return true;
}
When the user modifies a field on a page snap-in, it should call the PropertyBook’s setModified() method to let the PropertyBook know that a committable change has occurred. The PropertyBook will respond to the setModified( ) call by enabling its OK and Apply buttons, thereby giving the user the opportunity to commit the change. You should not call setModified() until after successfully returning true for initSnapin().
The first parameter for setModified(), isDirty, is a flag that indicates if the page’s data has changed since it was last saved. The flag set to true indicates that changes have been made. The flag set to false indicates that no changes have been made since the page was last saved. The second parameter, thePage, is a reference to the page snap-in. The this value references the current page.
public void setModified(boolean isDirty, PageSnapin thePage)
When a PageSnapin receives focus, the setActive() method will be called. If it is the first time that the page snap-in will receive the focus, the firstTime parameter will be set to true. The firstTimeShown parameter is an efficiency measure. Reading from a namespace can be a relatively time-consuming operation. Having all of the PropertyBook’s page snap-ins read when they are loaded might cause a noticeable delay. By having the page snap-in read only the first time that it is selected, the number of reads is reduced to only those pages that the user wants to view. The user interface is built at this time.
public void setActive( boolean firstTimeShown )
{
if( firstTimeShown )
{
// read data from source and populate page
}
}
Before the PropertyBook sets the focus to a different page (brings a different page to the front), the PropertyBook will give the PageSnapin currently owning the focus a chance to veto the change. This is done so that the PageSnapin with the current focus can check the validity (that is, the format) of its data.
To give the current focus holder an opportunity to veto the change, the PropertyBook calls the page’s killActive() method. If the owning PageSnapin determines that its data is OK, it should return true, indicating its willingness to proceed with the focus change. If the PageSnapin checks its data and finds it invalid, it should display an error dialog and then return false, effectively vetoing the change in focus.
For example, if one of the current page’s data fields is associated with a date and the entered date is in an unacceptable format, then when the PropertyBook calls the page’s killActivate( ) method, it should display a dialog asking the user to enter a date in an appropriate format and then return false.
public boolean killActive()
{
.
.// Check page data validity;
.// Return true if data is valid
.// else display error dialog, then return false
.
return true;
}
The canSave() method allows the page snap-in to validate dialog fields for each page or all pages in the property book before saving the data to a store with the saveData() method. The canSave() method is called in each of its page snap-ins to validate dialog fields, when the user selects either the OK button, or the Apply Now button. You should implement this method to give each page snap-in a chance to validate page data before saving data to storage. The only difference between this method and the killActive method is that this method is called when the user is trying to close the PropertyBook and the killActive() method is called when the user is trying to change the focus to a different page. This method can also be implemented by simply calling the killActive() method as shown below.
public boolean canSave()
{
.
. // Check page data validity
. // Return true if data is valid
. // Else display error dialog, then return false
return true; // or
. return killActive();
}
The saveData() method is called when the user selects either the OK button or the Apply Now button, and the canSave() method has returned true. If all the page snap-ins return true in their canSave() methods, this indicates to the PropertyBook that the save sequence can continue. The PropertyBook then calls the saveData() method of each of its page snap-ins. If, during the process of saving its data, the page snap-in has a problem, it can display a dialog informing the user why the operation was stopped and then return false, thereby stopping the operation for the remaining pages.
public boolean saveData()
{
.
. //If unable to save, display error dialog
. //and return false.
.
return true;
}
An alternate way to add property pages is to extend the AbstractPageSnapin class, which implements all methods in the PageSnapin interface as well as those methods derived from the Snapin interface. This abstract class was created so snap-in writers who want to create simple property page snap-ins can create them more easily. In addition to those methods derived from the PropertyBook, PageSnapin, and Snapin interfaces, the AbstractPageSnapin class defines the following methods:
The initAbstractSnapin() method is called by the property book to initialize the AbstractPageSnapin class. This method can be overridden if you extend the AbstractPageSnapin class and need to do additional initialization.
public boolean initAbstractSnapin()
{
return true;
}
The OnHide() method can be used to detect when your property page is being hidden.
public void OnHide()
{
}
The OnShow() method can be used to detect when your property page is being activated.
public void OnShow()
{
}
The setVisible() method overrides Component.setVisible() defined in the Component class. You cannot alter or override this method.
public final void setVisible(boolean flag)
{
super.setVisible( flag ); // call component’s setVisible
if( flag == true )
OnShow();
else
OnHide();
}
The shutdownAbstractSnapin() method is used to shut down the participating abstract snap-in. It is called by the shell for each snap-in when it is no longer required. This allows the snap-in to perform any necessary cleanup, such as removing itself as an event listener, as shown in the following implementation example.
public void shutdownAbstractSnapin()
{
shell.removeShellListener(this);
}
Use the following steps in writing a property page snap-in:
You might want to add several pages with only minor differences to a property book. If these pages are part of the same page snap-in collection, and you do not want to implement a separate class for each one, you can create a class that provides several snap-in pages. To do this see Writing Multiple Snap-ins in a Single Class.
To add menus or menu items into the ConsoleOne shell you must implement the MenuSnapin interface, which provides menu items that will be shown in the main shell menu. To provide a menu to be shown in a context menu of a specific object in the tree you must implement the PopupMenuSnapin interface (see Adding New Popup Menu Items). The MenuSnapin interface extends the Snapin interface from which the following four methods are derived. These methods must be implemented in your new menu snap-in.
These four Snapin interface methods are described in detail in Required Methods to Implement. In addition to implementing these methods in your new class, you must also register your snap-ins to the ConsoleOne shell by implementing the Registration interface. For a complete description of snap-in registration see Registering Your Snap-Ins.
The top and first level of the main menu can have an insertion point where all later menus that snap into that menu will come in. If the developer is creating a menu snap-in that will be in one of these locations and wants to define this insertion point, use a JMenuItem with the text equal to Shell.MENU_INSERTION_POINT. If this is not defined, all menus snapped in later will come in at the bottom. When building menus, ConsoleOne replaces this insertion point with the menus that are snapped into that menu.
Menus in ConsoleOne have locale-independent key names that are referred to in the getMenuLocation() method to define what menu to snap into. These keys are defined as the action command of the menu. When defining menus that will be snapped into, set the action command of the menu, using the setActionCommand() method, to be the key that other developers can use to register against. For ConsoleOne, the console snap-in’s main menu uses the English menu name as the key. To place items in nested menus, use the % as a separator. For example, to snap into the File/New submenu, return File%New from the getMenuLocation() method.
NOTE:For ConsoleOne menu items, you should always return the English menu names, even if you are adding menu items to a localized version of ConsoleOne. If you return localized menu names, they will appear as new (duplicate) menu items in the shell.
The following two methods are defined by the MenuSnapin interface.
The getMenuItems() method returns an array of JMenuItems objects or objects derived from JMenuItem (such as JMenu) that are to be placed in the ConsoleOne main menu. The following example creates two new menu items.
public JMenuItem[] getMenuItems()
{
JMenuItem[] menuItems = new JMenuItem[2];
menuItems[0] = new JMenuItem("Create User...");
menuItems[1] = new JMenuItem("Remove User...");
return menuItems;
}
The getMenuLocation() method should return the location of the new menu items in the current menu hierarchy. If the ancestors returned do not exist, they are created. If they do not exist, the new menu item is inserted at the snap-in point of insertion.
The following program example shows how to put the newly created menu items under the File menu.
public String getMenuLocation()
{
return "File";
}
To register a menu as a snap-in to the main menu within your snap-in, follow the example below.
public RegistrationItem[] getRegistration()
{
return new RegistrationItem[]
{
new RegistrationItem(
new NamespaceScope(Shell.SNAPIN_MENU,
"com.novell.sample.snapins.filesystem"),
getClass().getName())
}
}
Use the following steps to add a menu item to a namespace.
To add pop-up menu items into the ConsoleOne shell you must implement the PopupMenuSnapin interface, which provides a menu that will be shown in a pop-up menu of a specific object. To provide menu items that will be shown in the main shell menu you must implement the MenuSnapin interface (see Adding New Menu Items). The PopupMenuSnapin interface extends the Snapin interface from which the following four methods are derived. These methods must be implemented in your new menu snap-in.
These four Snapin interface methods are described in detail in Required Methods to Implement. In addition to implementing these methods in your new class, you must also register your snap-ins to the ConsoleOne shell by implementing the Registration interface. For a complete description of snap-in registration see Registering Your Snap-Ins.
The following two methods are defined by the PopupMenuSnapin interface.
When calling the getMenuItems() method you should return an array of JMenuItems objects or objects derived from JMenuItem (such as JMenu) that are to be placed in the pop-up menu. The following example creates two new pop-up menu items.
public JMenuItem[] getMenuItems()
{
JMenuItem[] menuItems = new JMenuItem[2];
menuItems[0] = new JMenuItem("Properties...");
menuItems[1] = new JMenuItem("Example...");
return menuItems;
}
The getMenuLocation() method should return the location of items to be added in the current User pop-up menu hierarchy.
The top and first level of a pop-up menu can have an insertion point where all later menus that snap into that menu will come in. If the developer is creating a pop-up menu snap-in that will be in one of these locations and wants to define this insertion point, use a JMenuItem with the text equal to Shell.MENU_INSERTION_POINT. If this is not defined, all pop-up menu items snapped in later will come in at the bottom.
Pop-up menus in ConsoleOne have locale-independent key names that are referred to in the getMenuLocation() method to define what menu to snap into. These keys are defined as the action command of the menu. When defining pop-up menus that will be snapped into, set the action command of the menu, using the setActionCommand() method, to be the key that other developers can use to register against. For ConsoleOne, the console snapin’s pop-up menus use the English menu name as the key.
For example, to place pop-up menu items at the top level, return "".
public String getMenuLocation()
{
return "";
}
To register the snap-in items as a pop-up menu, follow the example below.
public RegistrationItem[] getRegistration()
{
return new RegistrationItem[]
{
new RegistrationItem
(newNamespaceScope(Shell.SNAPIN_POPUP_MENU,
"com.novell.sample.snapins.filesystem"),
getClass().getName())
}
}
If you write a pop-up menu snapin that is not registered to a view, it will apply only to a single object selection. On the other hand, when your pop-up menu snap-in is registered to a view, then the pop-up menu will appear when no objects are selected, which makes it the default pop-up menu for the view. To get the pop-up menu to appear when more than one object is selected, you must register it to the NamespaceMultiSelectPopupMenuScope.
Use the following steps to add a pop-up menu item to a namespace.
To add status bar items to a view you must implement the StatusBarSnapin interface. The StatusBarSnapin interface extends the Snapin interface from which the following four methods are derived. These methods must be implemented in your new status bar snap-in.
These four Snapin interface methods are described in detail in Required Methods to Implement. In addition to implementing these methods in your new class, you must also register your snap-ins to the ConsoleOne shell by implementing the Registration interface. For a complete description of snap-in registration see Registering Your Snap-Ins.
You can add status bar items for any number of reasons, some of which might be:
Only one method is defined by the StatusBarSnapin interface, getStatusBarItem().
The getStatusBarItem() method should return a java.awt.Component object that will be placed on the shell’s status bar. This can be any object derived from java.awt.Component, such as a text field, progress bar, button, and so forth. The following example code creates a status bar item that is a label:
public Components getStatusBarItem()
{
Label label = new Label("StatusBar Item");
return label;
}
An alternate way to add status bar items is to extend the AbstractStatusBarSnapin class. This abstract class makes the creation of simple status bar items easier.The AbstractStatusBarSnapin interface defines five methods.
The getStatusBarText() method returns the text string to be placed in the status bar item. You should return the dynamic text that will appear within the 3D border of the status bar item. When the snap-in is first called and every time refresh() is called, getStatusBarText() will be called by the shell. For example, to display the size of a file named File:
public String getStatusBarText()
{
String statusBarText = "File length: ";
statusBarText += file.length();
return statusBarText;
}
The initAbstractSnapin() method allows you to make initializations when a snap-in is created. It also passes references to the InitSnapinInfo class. The following is an example of how this method can be implemented:
public boolean initAbstractSnapin(InitSnapinInfo info)
{
shell.addShellListener(this);
text = "Tree Selection: ";
setStatusBarWidth(20);
return true;
}
The info parameter contains data the snap-in can use, such as a reference to the shell, a reference to the snap-in type, and can contain a reference to the snap-in context data. This information is defined in the InitSnapinInfo class and the SnapinContext class.
The participating snap-in should return true if it is able to successfully complete initialization, or false if initialization fails.
The refresh() method refreshes the status bar item’s text by calling getStatusBarText() and then redrawing the status bar item. Snap-in can call this at any time to change the text displayed in the status bar item. For example, to refresh the status bar item whenever a new item in the tree is selected, implement the ShellListener interface, add the class to the shell as a listener, then implement the treeSelectionChanged() method. The refresh() method is called as shown below.
public void treeSelectionChanged(ShellEvent event)
{
refresh();
}
The setStatusBarWidth() method sets the width, in characters, of the status bar item.
The shutdownAbstractSnapin() method is used to shut down the participating abstract snap-in. It is called by the shell for each snap-in when it is no longer required. This allows the snap-in to perform any necessary cleanup, such as removing itself as an event listener, as shown in the following implementation example.
public void shutdownAbstractSnapin()
{
shell.removeShellListener(this);
}
Use the following steps to add new status bar items.
You might want to add several status bar items that have only minor differences. If these status bar items are part of the same snap-in collection, and you do not want to implement a separate class for each one, you can create one class that provides several status bar items. For more information on how to do this see Writing Multiple Snap-ins in a Single Class.
Sample File System Status Bar Program
To place toolbar items on the shell’s toolbar you must implement the ToolBarSnapin interface. The ToolBarSnapin interface extends the Snapin interface from which the following four methods are derived. These methods must be implemented in your new toolbar snap-in.
These four Snapin interface methods are described in detail in Required Methods to Implement. In addition to implementing these methods in your new class, you must also register your snap-ins to the ConsoleOne shell by implementing the Registration interface. For a complete description of snap-in registration see Registering Your Snap-Ins.
Only one method is defined by the StatusBarSnapin interface, getToolBarItem().
The getToolBarItem() method should return a component that will be placed on the toolbar. This can be any object derived from java.awt.Component, such as a push button, a group of buttons, a combo box, a check box, and so forth. The following code shows how an image button can be placed on the toolbar:
public Component getToolBarItem()
{
Image image = getImage();
JButton button = new JButton(new ImageIcon(image));
button.addActionListener(this);
return button;
}
An alternative to creatinging simple toolbar and menu snap-ins simultaneously is to extend the AbstractToolBarMenuSnapin class. This abstract class provides a simple image button on the toolbar and a menu item in the main menu. It is useful for the common situation where a menu item has a corresponding toolbar button. If you create a toolbar snap-in by extending the AbstractToolBarMenuSnapin class, you are limited to using simple image buttons on the toolbar, whereas the ToolBarSnapin interface allows you to place any object that is derived from java.awt.Component on the toolbar.
The AbstractToolBarMenuSnapin class defines the following methods:
The execute() method is called when the toolbar button is pressed or the menu item is selected. For example, to print a message when the tool is selected, you might do the following:
public void execute(boolean selection)
{
System.out.println("Snapin selected");
}
The getIcon() method should return the image to be placed in the toolbar item. The recommended image size is 32 by 32 pixels for large icons and 16 by 16 for small icons. The following example shows how to place an image from a resource bundle in the toolbar button.
public Image getIcon()
{
ResourceBundle myBundle = ResourceBundle.getBundle("MyBundle");
Image image = (Image) myBundle.getObject("ToolbarButtonImage");
return image;
}
The getMenuItems() method is derived from the MenuSnapin interface. The getMenuItems() method should return an array of JMenuItem objects or objects derived from JMenuItem (such as JMenu) that are to be placed in the ConsoleOne main menu. The following example creates two new menu items:
public JMenuItem[] getMenuItems()
{
JMenuItem[] menuItems = new JMenuItem[2];
menuItems[0] = new JMenuItem("Create User...");
menuItems[1] = new JMenuItem("Remove User...");
return menuItems;
}
The getMenuLocation() method is derived from the MenuSnapin interface. This method should return the location of the new menu item in the current menu hierarchy. To place the items in nested menus, use the % as a separator, for example use, File%New, to place an item under the New submenu of the File menu. If you do not override this method, the default for AbstractToolBarMenuSnapin is to place the menu item under the Tools menu. For example, the following code puts the newly created menu items under the File menu:
public String getMenuLocation()
{
return "File";
}
The getMenuName() method should return the localized string to be placed in the menu item. Place an ampersand (&) before a character in the string to specify that character as the mnemonic or shortcut character associated with the menu item. This method might be implemented as in the following example.
public String getMenuName()
{
return "E&xample Tool";
}
The getToolTip() method should return the localized string to be placed in the tool tip of the toolbar item. This method is implemented by the following simple command.
public String getToolTip()
{
return "Tool Tip";
}
You can implement in the initAbstractSnapin() method anything that needs to be initialized when the snap-in is created. It also passes references to the InitSnapinInfo class. The following is an example of how this method can be implemented:
public boolean initAbstractSnapin(InitSnapinInfo info)
{
shell.addShellListener(this);
return true;
}
The info parameter contains data the snap-in can use, such as a reference to the shell, a reference to the snap-in type, and can contain a reference to the snap-in context data. This information is defined in the InitSnapinInfo class and the SnapinContext class.
The participating snap-in should return true if it is able to successfully complete initialization, or false if initialization fails.
The shutdownAbstractSnapin() method is used to shut down the participating abstract snap-in. It is called by the shell for each snap-in when it is no longer required. This allows the snap-in to perform any necessary cleanup, such as removing itself as an event listener, as shown in the following implementation example.
public void shutdownAbstractSnapin()
{
shell.removeShellListener(this);
}
You should call the setEnabled() method to enable and disable the toolbar button and menu item of this snap-in. This is done through the following simple command:
setEnabled(false);
Use the following steps to add a toolbar item to the shell’s toolbar.
You might want to add several toolbar items that have only minor differences. If these toolbar items are part of the same snap-in collection, and you do not want to implement a separate class for each one, you can create one class that provides several toolbar items. To do this see Writing Multiple Snap-ins in a Single Class.
Sample File System Toolbar Program
The DynamicSnapin interface provides for late binding of snap-in registration. It serves as a place holder for arrays of snap-ins that will be registered dynamically after ConsoleOne is started. Thus, a dynamic snap-in class can return any number of snap-ins that are registered dynamically when they are needed.
When ConsoleOne needs the snap-ins, it calls the getSnapins() method, passing the scope that the dynamic snap-in was registered against (in case it has been registered to more than one scope) and the snap-in context. The SnapinContext parameter is dependent upon the snap-in type in the scope. The following sample code shows how the getSnapin() method could be implemented:
public Snapin[] getSnapins(Scope scope, SnapinContext context)
{
if(context instanceof ViewSnapinContext)
{
ViewSnapinContext viewContext = (ViewSnapinContext) context;
ObjectEntry entry = viewContext.getObjectEntry();
if(viewApplies(entry))
{
return new Snapin[]
{
new DynamicView()
};
}
else
{
return null;
}
}
return null;
}
For a list of the snap-in types and their valid scopes see Table 1 in Section 2.3, Snap-In Scopes. The dynamic snap-in then determines which snap-ins to create, creates them sets their instance data (if needed) and returns them.
The second method defined in the DynamicSnapin interface is the doSnapinsExist() method, which is used for performance. It returns a boolean indicating if snap-ins actually exist for the specified context (SnapinContext parameter). The boolean return is set to true if this snap-in would return any snap-ins from the getSnapin() method with the same parameters. For example, in the case of ExtendChildren snap-in, this method provides a fast way of simply checking to see if there are any snap-ins for a given object. This is important because it affects whether or not to show a leaf object in the tree whenever the tree is expanded.
You can use the following steps to write snap-ins that implement the DynamicSnapin interface:
If you have several snap-in items (menu items, status bar items, toolbar items or property pages) that are largely the same, rather than implement each snap-in item in a separate class, you can combine them into a single class that implements several snap-ins. This is done by implementing the setInstanceData() method defined in the Template interface. ConsoleOne calls the setInstanceData() method before calling the initSnapin() method of the registered snap-in.
The setInstanceData() method provides the snap-in a chance to uniquely identify itself if it is contained in a java class with other snap-ins. The snap-in’s instance data is passed in the RegistrationItem array when the getRegistration() method of the Registration interface is called. The instanceData can be null, or any valid java Object passed in the second RegistrationItem constructor. However, most often the instanceData will be a unique string or ID for a given snap-in. The following sample code shows how the setInstanceData() method might be implemented:
public void setInstanceData(Object instanceData)
{
this.instanceData = instanceData;
}
For example, you might want to add five different items to the toolbar without creating five separate classes. You can create a single class in which you implement the Template interface. In this implementation a key will be passed back to you indicating what personality the snap-in should take on based on the passed-in instance data.
You can use the following steps to write snap-ins that implement the Template interface in a single Java class.