1 /* 2 * This file is part of the LibreOffice project. 3 * 4 * This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 * 8 * This file incorporates work covered by the following license notice: 9 * 10 * Licensed to the Apache Software Foundation (ASF) under one or more 11 * contributor license agreements. See the NOTICE file distributed 12 * with this work for additional information regarding copyright 13 * ownership. The ASF licenses this file to you under the Apache 14 * License, Version 2.0 (the "License"); you may not use this file 15 * except in compliance with the License. You may obtain a copy of 16 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 17 */ 18 19 package org.libreoffice.example.java_scripts; 20 21 import javax.swing.*; 22 import javax.swing.tree.*; 23 import javax.swing.table.*; 24 import javax.swing.event.*; 25 import javax.swing.border.*; 26 import java.awt.*; 27 import java.awt.event.*; 28 import java.util.*; 29 import java.beans.*; 30 31 import com.sun.star.uno.UnoRuntime; 32 import com.sun.star.uno.Exception; 33 import com.sun.star.uno.Any; 34 import com.sun.star.uno.AnyConverter; 35 import com.sun.star.uno.Type; 36 import com.sun.star.uno.XComponentContext; 37 38 import com.sun.star.lang.XMultiComponentFactory; 39 import com.sun.star.lang.XComponent; 40 import com.sun.star.frame.XModel; 41 import com.sun.star.frame.FrameSearchFlag; 42 import com.sun.star.frame.XDispatchProvider; 43 import com.sun.star.frame.XDispatchHelper; 44 import com.sun.star.frame.XDispatch; 45 import com.sun.star.util.XURLTransformer; 46 import com.sun.star.beans.*; 47 import com.sun.star.script.XInvocation; 48 49 import com.sun.star.lib.uno.helper.PropertySet; 50 51 import com.sun.star.script.browse.XBrowseNode; 52 import com.sun.star.script.browse.BrowseNodeTypes; 53 import com.sun.star.script.browse.XBrowseNodeFactory; 54 import com.sun.star.script.browse.BrowseNodeFactoryViewTypes; 55 import com.sun.star.script.provider.XScriptContext; 56 import com.sun.star.script.provider.XScript; 57 import com.sun.star.script.provider.XScriptProvider; 58 59 public class ScriptSelector { 60 61 private static final int BIG_GAP = 10; 62 private static final int MED_GAP = 5; 63 64 private ScriptSelectorPanel selectorPanel; 65 ScriptSelector()66 public ScriptSelector() { 67 } 68 showOrganizer(final XScriptContext ctxt)69 public void showOrganizer(final XScriptContext ctxt) { 70 try { 71 XBrowseNode root = getRootNode(ctxt); 72 73 final XScriptProvider msp = 74 (XScriptProvider)UnoRuntime.queryInterface( 75 XScriptProvider.class, root); 76 77 final JFrame client = new JFrame("Script"); 78 79 selectorPanel = new ScriptSelectorPanel(root); 80 81 final JButton runButton, closeButton, createButton, 82 editButton, deleteButton; 83 84 runButton = new JButton("Run"); 85 runButton.setEnabled(false); 86 87 closeButton = new JButton("Close"); 88 89 editButton = new JButton("Edit"); 90 editButton.setEnabled(false); 91 92 JPanel northButtons = 93 new JPanel(new GridLayout(2, 1, MED_GAP, MED_GAP)); 94 95 northButtons.add(runButton); 96 northButtons.add(closeButton); 97 98 createButton = new JButton("Create"); 99 createButton.setEnabled(false); 100 101 deleteButton = new JButton("Delete"); 102 deleteButton.setEnabled(false); 103 104 JPanel southButtons = 105 new JPanel(new GridLayout(3, 1, MED_GAP, MED_GAP)); 106 107 southButtons.add(editButton); 108 southButtons.add(createButton); 109 southButtons.add(deleteButton); 110 111 selectorPanel.tree.addTreeSelectionListener( 112 new TreeSelectionListener() { 113 public void valueChanged(TreeSelectionEvent e) { 114 XBrowseNode xbn = selectorPanel.getSelection(); 115 XPropertySet props = (XPropertySet) 116 UnoRuntime.queryInterface(XPropertySet.class, xbn); 117 118 checkEnabled(props, "Creatable", createButton); 119 checkEnabled(props, "Deletable", deleteButton); 120 checkEnabled(props, "Editable", editButton); 121 122 if (xbn != null && 123 xbn.getType() == BrowseNodeTypes.SCRIPT) { 124 runButton.setEnabled(true); 125 } else { 126 runButton.setEnabled(false); 127 } 128 } 129 } 130 ); 131 132 ActionListener listener = new ActionListener() { 133 public void actionPerformed(ActionEvent event) { 134 if (event.getSource() == runButton) { 135 String uri = selectorPanel.textField.getText(); 136 137 try { 138 XScript script = msp.getScript(uri); 139 140 Object[][] out = new Object[1][0]; 141 out[0] = new Object[0]; 142 143 short[][] num = new short[1][0]; 144 num[0] = new short[0]; 145 146 script.invoke(new Object[0], num, out); 147 } catch (Exception e) { 148 e.printStackTrace(); 149 } 150 } else if (event.getSource() == closeButton) { 151 client.dispose(); 152 } else if (event.getSource() == editButton) { 153 DefaultMutableTreeNode node = 154 (DefaultMutableTreeNode) 155 selectorPanel.tree.getLastSelectedPathComponent(); 156 157 if (node == null) return; 158 159 showEditor(ctxt, node); 160 } else if (event.getSource() == createButton) { 161 DefaultMutableTreeNode node = 162 (DefaultMutableTreeNode) 163 selectorPanel.tree.getLastSelectedPathComponent(); 164 165 if (node == null) return; 166 167 doCreate(ctxt, node); 168 } else if (event.getSource() == deleteButton) { 169 DefaultMutableTreeNode node = 170 (DefaultMutableTreeNode) 171 selectorPanel.tree.getLastSelectedPathComponent(); 172 173 if (node == null) return; 174 175 doDelete(ctxt, node); 176 } 177 } 178 }; 179 180 runButton.addActionListener(listener); 181 closeButton.addActionListener(listener); 182 createButton.addActionListener(listener); 183 editButton.addActionListener(listener); 184 deleteButton.addActionListener(listener); 185 186 JPanel buttonPanel = new JPanel(new BorderLayout()); 187 buttonPanel.add(northButtons, BorderLayout.NORTH); 188 buttonPanel.add(southButtons, BorderLayout.SOUTH); 189 190 JPanel mainPanel = new JPanel(new BorderLayout(MED_GAP, MED_GAP)); 191 mainPanel.setBorder( 192 new EmptyBorder(BIG_GAP, BIG_GAP, BIG_GAP, BIG_GAP)); 193 mainPanel.add(selectorPanel, BorderLayout.CENTER); 194 mainPanel.add(buttonPanel, BorderLayout.EAST); 195 196 client.getContentPane().add(mainPanel); 197 client.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 198 client.setSize(500, 350); 199 200 // set the x and y locations so that the frame is in the 201 // centre of the screen 202 Dimension d = client.getToolkit().getScreenSize(); 203 204 int x = (int)((d.getWidth() - client.getWidth()) / 2); 205 int y = (int)((d.getHeight() - client.getHeight()) / 2); 206 207 client.setLocation(x, y); 208 209 client.show(); 210 } catch (com.sun.star.uno.RuntimeException rue) { 211 rue.printStackTrace(); 212 } catch (java.lang.Exception e) { 213 e.printStackTrace(); 214 } 215 } 216 showOrganizer(final XScriptContext ctxt, final com.sun.star.awt.MouseEvent e)217 public void showOrganizer(final XScriptContext ctxt, 218 final com.sun.star.awt.MouseEvent e) { 219 showOrganizer(ctxt); 220 } 221 showOrganizer(final XScriptContext ctxt, final com.sun.star.awt.ActionEvent e)222 public void showOrganizer(final XScriptContext ctxt, 223 final com.sun.star.awt.ActionEvent e) { 224 showOrganizer(ctxt); 225 } 226 doDelete( XScriptContext ctxt, DefaultMutableTreeNode node)227 private void doDelete( 228 XScriptContext ctxt, DefaultMutableTreeNode node) { 229 Object obj = node.getUserObject(); 230 XInvocation inv = 231 (XInvocation)UnoRuntime.queryInterface( 232 XInvocation.class, obj); 233 Object[] args = new Object[] { ctxt }; 234 235 try { 236 Object result = inv.invoke("Deletable", args, 237 new short[1][0], new Object[1][0]); 238 239 if (result != null && AnyConverter.toBoolean(result) == true) { 240 selectorPanel.removeNode(node); 241 } 242 } catch (Exception e) { 243 e.printStackTrace(); 244 } 245 } 246 doCreate( XScriptContext ctxt, DefaultMutableTreeNode node)247 private void doCreate( 248 XScriptContext ctxt, DefaultMutableTreeNode node) { 249 Object obj = node.getUserObject(); 250 XInvocation inv = 251 (XInvocation)UnoRuntime.queryInterface( 252 XInvocation.class, obj); 253 Object[] args = new Object[] { ctxt }; 254 255 try { 256 Object result = inv.invoke("Creatable", args, 257 new short[1][0], new Object[1][0]); 258 259 if (result != null) { 260 XBrowseNode xbn = (XBrowseNode) 261 AnyConverter.toObject(new Type(XBrowseNode.class), result); 262 selectorPanel.addNode(node, xbn); 263 } 264 } catch (Exception e) { 265 e.printStackTrace(); 266 } 267 } 268 showEditor( XScriptContext ctxt, DefaultMutableTreeNode node)269 private void showEditor( 270 XScriptContext ctxt, DefaultMutableTreeNode node) { 271 Object obj = node.getUserObject(); 272 XInvocation inv = 273 (XInvocation)UnoRuntime.queryInterface( 274 XInvocation.class, obj); 275 Object[] args = new Object[] { ctxt }; 276 277 try { 278 inv.invoke("Editable", args, 279 new short[1][0], new Object[1][0]); 280 } catch (Exception e) { 281 e.printStackTrace(); 282 } 283 } 284 checkEnabled(XPropertySet props, String name, JButton button)285 private void checkEnabled(XPropertySet props, String name, 286 JButton button) { 287 boolean enable = false; 288 289 try { 290 if (props != null) { 291 Object o = props.getPropertyValue(name); 292 enable = AnyConverter.toBoolean( 293 props.getPropertyValue(name)); 294 } 295 } catch (com.sun.star.lang.IllegalArgumentException iae) { 296 // leave enable set to false 297 } catch (com.sun.star.beans.UnknownPropertyException upe) { 298 // leave enable set to false 299 } catch (com.sun.star.lang.WrappedTargetException wte) { 300 // leave enable set to false 301 } 302 303 button.setEnabled(enable); 304 } 305 getRootNode(XScriptContext ctxt)306 private XBrowseNode getRootNode(XScriptContext ctxt) { 307 308 XBrowseNode result = null; 309 310 311 XComponentContext xcc = ctxt.getComponentContext(); 312 XMultiComponentFactory xmcf = xcc.getServiceManager(); 313 XBrowseNodeFactory xBrowseFac = (XBrowseNodeFactory) 314 UnoRuntime.queryInterface(XBrowseNodeFactory.class, xcc.getValueByName( 315 "/singletons/com.sun.star.script.browse.theBrowseNodeFactory")); 316 317 318 result = (XBrowseNode)UnoRuntime.queryInterface( 319 XBrowseNode.class, xBrowseFac.createView( 320 BrowseNodeFactoryViewTypes.MACROORGANIZER)); 321 return result; 322 } 323 } 324 325 class ScriptSelectorPanel extends JPanel { 326 327 private XBrowseNode myrootnode = null; 328 public JTextField textField; 329 public JTree tree; 330 public DefaultTreeModel treeModel; 331 ScriptSelectorPanel(XBrowseNode root)332 public ScriptSelectorPanel(XBrowseNode root) { 333 this.myrootnode = root; 334 initUI(); 335 } 336 getSelection()337 public XBrowseNode getSelection() { 338 DefaultMutableTreeNode node = (DefaultMutableTreeNode) 339 tree.getLastSelectedPathComponent(); 340 341 if (node == null) { 342 return null; 343 } 344 345 return (XBrowseNode)node.getUserObject(); 346 } 347 initUI()348 private void initUI() { 349 setLayout(new BorderLayout()); 350 351 DefaultMutableTreeNode top = 352 new DefaultMutableTreeNode(myrootnode) { 353 public String toString() { 354 return ((XBrowseNode)getUserObject()).getName(); 355 } 356 }; 357 initNodes(myrootnode, top); 358 treeModel = new DefaultTreeModel(top); 359 tree = new JTree(treeModel); 360 361 tree.setCellRenderer(new ScriptTreeRenderer()); 362 363 tree.getSelectionModel().setSelectionMode 364 (TreeSelectionModel.SINGLE_TREE_SELECTION); 365 366 tree.addTreeSelectionListener(new TreeSelectionListener() { 367 public void valueChanged(TreeSelectionEvent e) { 368 XBrowseNode xbn = getSelection(); 369 XPropertySet props = (XPropertySet)UnoRuntime.queryInterface( 370 XPropertySet.class, xbn); 371 372 if (xbn == null) { 373 textField.setText(""); 374 return; 375 } 376 377 String str = xbn.getName(); 378 379 if (xbn.getType() == BrowseNodeTypes.SCRIPT && props != null) { 380 try { 381 str = AnyConverter.toString( 382 props.getPropertyValue("URI")); 383 } catch (Exception ignore) { 384 // default will be used 385 } 386 } 387 388 textField.setText(str); 389 } 390 }); 391 392 JScrollPane scroller = new JScrollPane(tree); 393 add(scroller, BorderLayout.CENTER); 394 395 textField = new JTextField(); 396 add(textField, BorderLayout.SOUTH); 397 } 398 removeNode(DefaultMutableTreeNode node)399 public void removeNode(DefaultMutableTreeNode node) { 400 MutableTreeNode parent = (MutableTreeNode)(node.getParent()); 401 402 if (parent != null) { 403 treeModel.removeNodeFromParent(node); 404 } 405 } 406 addNode(DefaultMutableTreeNode parent, XBrowseNode xbn)407 public void addNode(DefaultMutableTreeNode parent, XBrowseNode xbn) { 408 DefaultMutableTreeNode newNode = 409 new DefaultMutableTreeNode(xbn) { 410 public String toString() { 411 return ((XBrowseNode)getUserObject()).getName(); 412 } 413 }; 414 415 treeModel.insertNodeInto(newNode, parent, parent.getChildCount()); 416 tree.scrollPathToVisible(new TreePath(newNode.getPath())); 417 } 418 initNodes(XBrowseNode parent, DefaultMutableTreeNode top)419 private void initNodes(XBrowseNode parent, DefaultMutableTreeNode top) { 420 if (parent == null || parent.hasChildNodes() == false) { 421 return; 422 } 423 424 XBrowseNode[] children = parent.getChildNodes(); 425 426 try { 427 if (children != null) { 428 for (int i = 0; i < children.length; i++) { 429 if (children[i] == null) { 430 continue; 431 } 432 433 DefaultMutableTreeNode newNode = 434 new DefaultMutableTreeNode(children[i]) { 435 public String toString() { 436 return ((XBrowseNode)getUserObject()).getName(); 437 } 438 }; 439 top.add(newNode); 440 initNodes(children[i], newNode); 441 } 442 } 443 } catch (java.lang.Exception e) { 444 e.printStackTrace(); 445 } 446 } 447 } 448 449 class ScriptTreeRenderer extends DefaultTreeCellRenderer { 450 451 private ImageIcon sofficeIcon; 452 private ImageIcon scriptIcon; 453 private ImageIcon containerIcon; 454 ScriptTreeRenderer()455 public ScriptTreeRenderer() { 456 sofficeIcon = new ImageIcon(getClass().getResource("soffice.gif")); 457 scriptIcon = new ImageIcon(getClass().getResource("script.gif")); 458 containerIcon = new ImageIcon(getClass().getResource("container.gif")); 459 } 460 getTreeCellRendererComponent( JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus)461 public Component getTreeCellRendererComponent( 462 JTree tree, 463 Object value, 464 boolean sel, 465 boolean expanded, 466 boolean leaf, 467 int row, 468 boolean hasFocus) { 469 470 super.getTreeCellRendererComponent( 471 tree, value, sel, 472 expanded, leaf, row, 473 hasFocus); 474 475 DefaultMutableTreeNode node = (DefaultMutableTreeNode)value; 476 XBrowseNode xbn = (XBrowseNode)node.getUserObject(); 477 478 if (xbn.getType() == BrowseNodeTypes.SCRIPT) { 479 setIcon(scriptIcon); 480 } else if (xbn.getType() == BrowseNodeTypes.CONTAINER) { 481 setIcon(containerIcon); 482 } else if (xbn.getType() == BrowseNodeTypes.ROOT) { 483 setIcon(sofficeIcon); 484 } 485 486 return this; 487 } 488 } 489