禁用的命令

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

Jump to: navigation, search



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


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


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


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

禁用命令功能的工作原理


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


配置

禁用命令功能使用配置分支 org.openoffice.Office.Commands 来读取应禁用的命令。以下模式适用:

  <?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>

已禁用命令的配置模式非常简单。org.openoffice.Office.Commands 分支具有一个名为 Execute 的组。此组仅拥有一个名为 Disabled 的集。Disabled 集支持类型 CommandType 的节点。下表说明了受支持的 CommandType 的属性。

CommandType 组的属性
oor:component-data 字符串型。它在 Disabled 集中必须是唯一的,但是对禁用命令功能的实现没有其他意义。使用连续编号方案;甚至允许使用数字。
Command 字符串型。这是带有前导协议的命令名称。这意味着命令 URL .uno:Open(将显示文件 – 打开对话框)必须编写为 Open

有效的命令可以在 OpenOffice.org 网页上框架项目的“文档”区域命令名称的索引文档中找到。OpenOffice.org SDK 还包括最新的命令名称列表

更多有关命令名称的信息请访问http://wiki.services.openoffice.org/wiki/Framework/Article/OpenOffice.org_2.x_Commands


以下示例显示了禁用文件 – 打开编辑 – 全选帮助 – 关于 OpenOffice.org文件 – 退出命令的配置文件。

  <?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>


在运行时禁用命令

根据定义的起始点,以下代码示例首先删除在配置分支 org.openoffice.Office.Commands 的用户层定义的所有命令。然后检查它是否可以获取某些预设的命令的分发对象。

接着该示例将禁用这些命令并尝试再次获取它们的分发对象。最后,代码将再次删除已禁用的命令,否则 OpenOffice.org 将无法充分使用。

  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