禁用的命令

From Apache OpenOffice Wiki
< Zh‎ | Documentation
Revision as of 09:27, 6 August 2008 by Jirong (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search



在 OpenOffice.org 中,有时可能需要禁用某些功能以防止用户意外地更改或破坏文档。 OpenOffice.org 具有一个禁用命令的列单,这些命令可以由用户和开发者通过配置 API 进行维护。


命令请求可由任意对象创建,但在大多数情况下,是由用户界面对象创建的。以工具栏为例,工具栏上作用于办公软件组件的各种功能都以按钮的形式出现。单击按钮时,所需功能即被执行。如果指定给按钮的代码拥有适当的命令 URL,分发框架可以通过创建请求并查找可以处理请求的组件来处理用户的操作。


分发框架与设计模式责任链共同起作用:如果组件要执行请求,它需要了解的全部内容就是可以执行请求的对象链中的最一个环节。如果此对象获取请求,它将检查是否可以处理该请求,如果不能,则将其传送到下一个链成员,直到请求被执行或到达链的末尾。禁用命令实现是第一个链成员,因此可以作为所有禁用的命令的“墙”,这些命令便不会被发送到下一个链成员,并随即消失。


下列插图说明禁用命令功能如何影响常规的命令应用程序流。

禁用命令功能的工作原理


Documentation caution.png 由于禁用命令实现是分发链中的第一个环节,所以没有办法避开它。已禁用的命令必须从列表中删除,否则命令将保持禁用状态。


Configuration

The disable commands feature uses the configuration branch org.openoffice.Office.Commands to read which commands should be disabled. The following schema applies:

  <?xml version='1.0' encoding='UTF-8'?>
  <oor:component-schema oor:name="Commands" oor:package="org.openoffice.Office" xml:lang="en-US" xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <templates>
          <group oor:name="CommandType">
              <prop oor:name="Command" oor:type="xs:string"/>
          </group>
      </templates>
      <component>
          <group oor:name="Execute">
              <set oor:name="Disabled" oor:node-type="CommandType"/>
          </group>
      </component>
  </oor:component-schema></nowiki>

The configuration schema for disabled commands is very simple. The org.openoffice.Office.Commands branch has a group called Execute. This group has only one set called Disabled. The Disabled set supports nodes of the type CommandType. The following table describes the supported properties of CommandType.

Properties of the CommandType group
oor:component-data string. It must be unique inside the Disabled set, but has no additional meaning for the implementation of the disable commands feature. Use a consecutive numbering scheme; even numbers are allowed.
Command string. This is the command name with the preceding protocol. That means the command URL .uno:Open (which shows the File – Open dialog) must be written as Open.

The valid commands can be found in the document Index of Command Names in the Documentation section of the framework project on the OpenOffice.org web page. The OpenOffice.org SDK also includes the latest list of command names. Additional information regarding Command names is available in: [1]

The example below shows a configuration file that disables the commands for File – Open, Edit – Select All, Help – About OpenOffice.org and File – Exit.

  <?xml version="1.0" encoding="UTF-8" ?>
  <oor:component-data oor:name="Commands" oor:package="org.openoffice.Office" xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <node oor:name="Execute">
          <node oor:name="Disabled">
              <node oor:name="m1" oor:op="replace">
                  <prop oor:name="Command">
                      <value>Open</value>
                  </prop>
              </node>
              <node oor:name="m2" oor:op="replace">
                  <prop oor:name="Command">
                      <value>SelectAll</value>
                  </prop>
              </node>
              <node oor:name="m3" oor:op="replace">
                  <prop oor:name="Command">
                      <value>About</value>
                  </prop>
              </node>
              <node oor:name="m4" oor:op="replace">
                  <prop oor:name="Command">
                      <value>Quit</value>
                  </prop>
              </node>
          </node>
      </node>
  </oor:component-data></nowiki>

Disabling Commands at Runtime

The following code example first removes all commands that were defined in the user layer of the configuration branch org.openoffice.Office.Commands as having a defined starting point. Then it checks if it can get dispatch objects for some pre-defined commands.Then the example disables these commands and tries to get dispatch objects for them again. At the end, the code removes the disabled commands again, otherwise OpenOffice.org would not be fully usable any longer.

  import com.sun.star.bridge.XUnoUrlResolver;
  import com.sun.star.uno.UnoRuntime;
  import com.sun.star.uno.XComponentContext;
  import com.sun.star.lang.XMultiComponentFactory;
  import com.sun.star.beans.XPropertySet;
  import com.sun.star.beans.PropertyValue;
  import com.sun.star.lang.XMultiServiceFactory;
  import com.sun.star.lang.XSingleServiceFactory;
  import com.sun.star.util.XURLTransformer;
  import com.sun.star.frame.XDesktop;
 
  import com.sun.star.beans.UnknownPropertyException;
 
  /*
   *  Provides example code how to enable/disable
   *  commands.
   */
  public class DisableCommandsTest extends java.lang.Object {
 
      /*
       *  A list of command names
       */
      final static private String[] aCommandURLTestSet =
      {
          new String( "Open" ),
          new String( "About" ),
          new String( "SelectAll" ),
          new String( "Quit" ),
      };
 
      private static XComponentContext xRemoteContext = null;
      private static XMultiComponentFactory xRemoteServiceManager = null;
      private static XURLTransformer xTransformer = null;
      private static XMultiServiceFactory xConfigProvider = null;
 
      /*
       *  @param args the command line arguments
       */
      public static void main(String[] args) {
 
          try {
              // connect
              XComponentContext xLocalContext =
              com.sun.star.comp.helper.Bootstrap.createInitialComponentContext(null);
              XMultiComponentFactory xLocalServiceManager = xLocalContext.getServiceManager();
              Object urlResolver = xLocalServiceManager.createInstanceWithContext(
                  "com.sun.star.bridge.UnoUrlResolver", xLocalContext);
              XUnoUrlResolver xUnoUrlResolver = (XUnoUrlResolver) UnoRuntime.queryInterface( 
                  XUnoUrlResolver.class, urlResolver );
              Object initialObject = xUnoUrlResolver.resolve( 
              "uno:socket,host=localhost,port=2083;urp;StarOffice.ServiceManager");
              XPropertySet xPropertySet = (XPropertySet)UnoRuntime.queryInterface(
                  XPropertySet.class, initialObject);
              Object context = xPropertySet.getPropertyValue("DefaultContext");
              xRemoteContext = (XComponentContext)UnoRuntime.queryInterface(
                  XComponentContext.class, context);
              xRemoteServiceManager = xRemoteContext.getServiceManager();
              Object transformer = xRemoteServiceManager.createInstanceWithContext(
                  "com.sun.star.util.URLTransformer", xRemoteContext);
              xTransformer = (com.sun.star.util.XURLTransformer)UnoRuntime.queryInterface(
                  com.sun.star.util.XURLTransformer.class, transformer);
 
              Object configProvider = xRemoteServiceManager.createInstanceWithContext(
                  "com.sun.star.configuration.ConfigurationProvider", xRemoteContext);
              xConfigProvider = (com.sun.star.lang.XMultiServiceFactory)UnoRuntime.queryInterface(
                  com.sun.star.lang.XMultiServiceFactory.class, configProvider);
 
              // First we need a defined starting point. So we have to remove
              // all commands from the disabled set!
              enableCommands();
 
              // Check if the commands are usable
              testCommands(false);
 
              // Disable the commands
              disableCommands();
 
              // Now the commands should not be usable anymore
              testCommands(true);
 
              // Remove disable commands to make Office usable again
              enableCommands();
          }
          catch (java.lang.Exception e){
              e.printStackTrace();
          } 
          finally {
              System.exit(0);
          }
      }
 
      /**
       *  Test the commands that we enabled/disabled
       */
      private static void testCommands(boolean bDisabledCmds) throws com.sun.star.uno.Exception {
          // We need the desktop to get access to the current frame
          Object desktop = xRemoteServiceManager.createInstanceWithContext(
              "com.sun.star.frame.Desktop", xRemoteContext );
          com.sun.star.frame.XDesktop xDesktop = (com.sun.star.frame.XDesktop)UnoRuntime.queryInterface(
              com.sun.star.frame.XDesktop.class, desktop);
          com.sun.star.frame.XFrame xFrame = xDesktop.getCurrentFrame();
          com.sun.star.frame.XDispatchProvider xDispatchProvider = null;
          if (xFrame != null) {
              // We have a frame. Now we need access to the dispatch provider.
              xDispatchProvider = (com.sun.star.frame.XDispatchProvider)UnoRuntime.queryInterface( 
                  com.sun.star.frame.XDispatchProvider.class, xFrame );
              if (xDispatchProvider != null) {
                  // As we have the dispatch provider we can now check if we get a dispatch
                  // object or not.
                  for (int n = 0; n < aCommandURLTestSet.length; n++) {
                      // Prepare the URL
                      com.sun.star.util.URL[] aURL = new com.sun.star.util.URL[1];
                      aURL[0] = new com.sun.star.util.URL();
                      com.sun.star.frame.XDispatch xDispatch = null;
 
                      aURL[0].Complete = ".uno:" + aCommandURLTestSet[n];
                      xTransformer.parseSmart(aURL, ".uno:");
 
                      // Try to get a dispatch object for our URL
                      xDispatch = xDispatchProvider.queryDispatch(aURL[0], "", 0);
 
                      if (xDispatch != null) {
                          if (bDisabledCmds)
                              System.out.println("Something is wrong, I got dispatch object for " 
                                  + aURL[0].Complete);
                          else
                              System.out.println("Ok, dispatch object for " + aURL[0].Complete);
                      }
                      else {
                          if (!bDisabledCmds)
                              System.out.println("Something is wrong, I cannot get dispatch   object for " 
                                  + aURL[0].Complete);
                          else
                              System.out.println("Ok, no dispatch object for " + aURL[0].Complete);
                      }
                      resetURL(aURL[0]);
                  }
              }
              else
                  System.out.println("Couldn't get XDispatchProvider from Frame!");
          }
          else
              System.out.println("Couldn't get current Frame from Desktop!");
      }
 
      /**
       *  Ensure that there are no disabled commands in the user layer. The
       *  implementation removes all commands from the disabled set!
       */
      private static void enableCommands() {
          // Set the root path for our configuration access
          com.sun.star.beans.PropertyValue[] lParams = new com.sun.star.beans.PropertyValue[1];
 
          lParams[0] = new com.sun.star.beans.PropertyValue();
          lParams[0].Name = new String("nodepath");
          lParams[0].Value = "/org.openoffice.Office.Commands/Execute/Disabled";
 
          try {
              // Create configuration update access to have write access to the configuration
              Object xAccess = xConfigProvider.createInstanceWithArguments( 
"com.sun.star.configuration.ConfigurationUpdateAccess", lParams);
 
              com.sun.star.container.XNameAccess xNameAccess = (com.sun.star.container.XNameAccess)
              UnoRuntime.queryInterface(com.sun.star.container.XNameAccess.class, xAccess);
              if (xNameAccess != null) {
                  // We need the XNameContainer interface to remove the nodes by name
                  com.sun.star.container.XNameContainer xNameContainer =
                      (com.sun.star.container.XNameContainer)
                  UnoRuntime.queryInterface(com.sun.star.container.XNameContainer.class, xAccess);
 
                  // Retrieves the names of all Disabled nodes
                  String[] aCommandsSeq = xNameAccess.getElementNames();
                  for (int n = 0; n < aCommandsSeq.length; n++) {
                      try {
                          // remove the node
                          xNameContainer.removeByName( aCommandsSeq[n]);
                      }
                      catch (com.sun.star.lang.WrappedTargetException e) {
                      }
                      catch (com.sun.star.container.NoSuchElementException e) {
                      }
                  }
              } 
 
              // Commit our changes
              com.sun.star.util.XChangesBatch xFlush =
              (com.sun.star.util.XChangesBatch)UnoRuntime.queryInterface(
                  com.sun.star.util.XChangesBatch.class, xAccess);
              xFlush.commitChanges();
          }    
          catch (com.sun.star.uno.Exception e) {
              System.out.println("Exception detected!");
              System.out.println(e);
          }
      }
 
      /**
       *  Disable all commands defined in the aCommandURLTestSet array
       */
      private static void disableCommands() {
      // Set the root path for our configuration access
      com.sun.star.beans.PropertyValue[] lParams = new com.sun.star.beans.PropertyValue[1];
      lParams[0] = new com.sun.star.beans.PropertyValue();
      lParams[0].Name = new String("nodepath");
      lParams[0].Value = "/org.openoffice.Office.Commands/Execute/Disabled";
 
      try {
          // Create configuration update access to have write access to the configuration
          Object xAccess = xConfigProvider.createInstanceWithArguments( 
          "com.sun.star.configuration.ConfigurationUpdateAccess", lParams);
 
          com.sun.star.lang.XSingleServiceFactory xSetElementFactory = 
          (com.sun.star.lang.XSingleServiceFactory)UnoRuntime.queryInterface(
              com.sun.star.lang.XSingleServiceFactory.class, xAccess);
 
          com.sun.star.container.XNameContainer xNameContainer =
          (com.sun.star.container.XNameContainer)UnoRuntime.queryInterface(
              com.sun.star.container.XNameContainer.class, xAccess );
 
          if (xSetElementFactory != null && xNameContainer != null) {
              Object[] aArgs = new Object[0];
 
              for (int i = 0; i < aCommandURLTestSet.length; i++) {
                  // Create the nodes with the XSingleServiceFactory of the configuration
                      Object xNewElement = xSetElementFactory.createInstanceWithArguments( aArgs );
                      if (xNewElement != null) {
                          // We have a new node. To set the properties of the node we need
                          // the XPropertySet interface.
                          com.sun.star.beans.XPropertySet xPropertySet = 
                          (com.sun.star.beans.XPropertySet)UnoRuntime.queryInterface( com.sun.star.beans.XPropertySet.class,
                              xNewElement );
 
                          if (xPropertySet != null) {
                              // Create a unique node name.
                              String aCmdNodeName = new String("Command-");
                              aCmdNodeName += i;
 
                              // Insert the node into the Disabled set
                              xPropertySet.setPropertyValue("Command", aCommandURLTestSet[i]);
                              xNameContainer.insertByName(aCmdNodeName, xNewElement);
                          }
                      }
                  }
 
                  // Commit our changes
                  com.sun.star.util.XChangesBatch xFlush = (com.sun.star.util.XChangesBatch)
                  UnoRuntime.queryInterface(com.sun.star.util.XChangesBatch.class, xAccess);
                  xFlush.commitChanges();
              } 
          }
          catch (com.sun.star.uno.Exception e) {
              System.out.println("Exception detected!");
              System.out.println(e);
          }
      } 
 
      /**
       *  reset URL so it can be reused
       *
       *  @param aURL
       *  the URL that should be reseted
       */
      private static void resetURL(com.sun.star.util.URL aURL) {
          aURL.Protocol = "";
          aURL.User = "";
          aURL.Password = "";
          aURL.Server = "";
          aURL.Port = 0;
          aURL.Path = "";
          aURL.Name = "";
          aURL.Arguments = "";
          aURL.Mark = "";
          aURL.Main = "";
          aURL.Complete = "";
      }
  }
Content on this page is licensed under the Public Documentation License (PDL).
Personal tools