1 /* 2 * Created on 2 juil. 2003 3 * Copyright (C) Azureus Software, Inc, All Rights Reserved. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation; either version 2 8 * of the License, or (at your option) any later version. 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * You should have received a copy of the GNU General Public License 14 * along with this program; if not, write to the Free Software 15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16 * 17 */ 18 package org.gudy.azureus2.ui.swt.views; 19 20 import java.util.*; 21 22 import org.eclipse.swt.SWT; 23 import org.eclipse.swt.custom.SashForm; 24 import org.eclipse.swt.custom.ScrolledComposite; 25 import org.eclipse.swt.custom.StackLayout; 26 import org.eclipse.swt.events.*; 27 import org.eclipse.swt.graphics.*; 28 import org.eclipse.swt.layout.*; 29 import org.eclipse.swt.widgets.*; 30 import org.eclipse.swt.widgets.List; 31 import org.gudy.azureus2.core3.config.COConfigurationManager; 32 import org.gudy.azureus2.core3.internat.MessageText; 33 import org.gudy.azureus2.core3.logging.LogEvent; 34 import org.gudy.azureus2.core3.logging.LogIDs; 35 import org.gudy.azureus2.core3.logging.Logger; 36 import org.gudy.azureus2.core3.util.*; 37 import org.gudy.azureus2.core3.util.Timer; 38 import org.gudy.azureus2.plugins.ui.UIInputReceiver; 39 import org.gudy.azureus2.plugins.ui.UIInputReceiverListener; 40 import org.gudy.azureus2.plugins.ui.config.ConfigSection; 41 import org.gudy.azureus2.pluginsimpl.local.ui.config.ConfigSectionRepository; 42 import org.gudy.azureus2.ui.swt.Messages; 43 import org.gudy.azureus2.ui.swt.SimpleTextEntryWindow; 44 import org.gudy.azureus2.ui.swt.Utils; 45 import org.gudy.azureus2.ui.swt.plugins.*; 46 import org.gudy.azureus2.ui.swt.views.configsections.*; 47 48 import com.aelitis.azureus.core.AzureusCore; 49 import com.aelitis.azureus.core.AzureusCoreFactory; 50 import com.aelitis.azureus.core.AzureusCoreRunningListener; 51 import com.aelitis.azureus.ui.swt.imageloader.ImageLoader; 52 53 @SuppressWarnings("deprecation") 54 public class ConfigView implements UISWTViewEventListener { 55 public static final String VIEW_ID = UISWTInstance.VIEW_CONFIG; 56 private static final LogIDs LOGID = LogIDs.GUI; 57 public static final String sSectionPrefix = "ConfigView.section."; 58 59 Map<TreeItem, ConfigSection> sections = new HashMap<TreeItem, ConfigSection>(); 60 // Only access on SWT Thread 61 java.util.List<ConfigSection> sectionsCreated = new ArrayList<ConfigSection>(1); 62 Composite cConfig; 63 Composite cConfigSection; 64 StackLayout layoutConfigSection; 65 Label lHeader; 66 Label usermodeHint; 67 Font headerFont; 68 Font filterFoundFont; 69 Tree tree; 70 ArrayList<ConfigSection> pluginSections; 71 72 private Timer filterDelayTimer; 73 private String filterText = ""; 74 private Label lblX; 75 private Listener scResizeListener; 76 77 private Image imgSmallX; 78 private Image imgSmallXGray; 79 private String startSection; 80 private UISWTView swtView; 81 ConfigView()82 public ConfigView() { 83 } 84 initialize(final Composite composite)85 private void initialize(final Composite composite) { 86 // need to initalize composite now, since getComposite can 87 // be called at any time 88 cConfig = new Composite(composite, SWT.NONE); 89 90 GridLayout configLayout = new GridLayout(); 91 configLayout.marginHeight = 0; 92 configLayout.marginWidth = 0; 93 cConfig.setLayout(configLayout); 94 GridData gridData = new GridData(GridData.FILL_BOTH); 95 Utils.setLayoutData(cConfig, gridData); 96 97 final Label label = new Label(cConfig, SWT.CENTER); 98 Messages.setLanguageText(label, "view.waiting.core"); 99 gridData = new GridData(GridData.FILL_BOTH); 100 Utils.setLayoutData(label, gridData); 101 102 // Need to delay initialation until core is done so we can guarantee 103 // all config sections are loaded (ie. plugin ones). 104 // TODO: Maybe add them on the fly? 105 AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { 106 public void azureusCoreRunning(AzureusCore core) { 107 Utils.execSWTThread(new AERunnable() { 108 public void runSupport() { 109 _initialize(composite); 110 label.dispose(); 111 composite.layout(true, true); 112 } 113 }); 114 } 115 }); 116 } 117 _initialize(final Composite composite)118 private void _initialize(final Composite composite) { 119 120 GridData gridData; 121 /* 122 /--cConfig-----------------------------------------------------------\ 123 | ###SashForm#form################################################## | 124 | # /--cLeftSide-\ /--cRightSide---------------------------------\ # | 125 | # | ##tree#### | | ***cHeader********************************* | # | 126 | # | # # | | * lHeader usermodeHint * | # | 127 | # | # # | | ******************************************* | # | 128 | # | # # | | ###Composite cConfigSection################ | # | 129 | # | # # | | # # | # | 130 | # | # # | | # # | # | 131 | # | # # | | # # | # | 132 | # | ########## | | # # | # | 133 | # |txtFilter X | | ########################################### | # | 134 | # \------------/ \---------------------------------------------/ # | 135 | ################################################################## | 136 | [Buttons] | 137 \--------------------------------------------------------------------/ 138 */ 139 try { 140 Display d = composite.getDisplay(); 141 GridLayout configLayout; 142 143 SashForm form = new SashForm(cConfig,SWT.HORIZONTAL); 144 gridData = new GridData(GridData.FILL_BOTH); 145 Utils.setLayoutData(form, gridData); 146 147 Composite cLeftSide = new Composite(form, SWT.BORDER); 148 gridData = new GridData(GridData.FILL_BOTH); 149 Utils.setLayoutData(cLeftSide, gridData); 150 151 FormLayout layout = new FormLayout(); 152 cLeftSide.setLayout(layout); 153 154 Composite cFilterArea = new Composite(cLeftSide, SWT.NONE); 155 cFilterArea.setLayout(new FormLayout()); 156 157 final Text txtFilter = new Text(cFilterArea, SWT.BORDER); 158 final String sFilterText = MessageText.getString("ConfigView.filter"); 159 txtFilter.setText(sFilterText); 160 txtFilter.selectAll(); 161 txtFilter.addModifyListener(new ModifyListener() { 162 public void modifyText(ModifyEvent e) { 163 filterTree(txtFilter.getText()); 164 } 165 }); 166 txtFilter.addMouseListener(new MouseAdapter() { 167 public void mouseDown(MouseEvent e) { 168 if (txtFilter.getText().equals(sFilterText)) { 169 txtFilter.selectAll(); 170 } 171 } 172 }); 173 txtFilter.setFocus(); 174 175 ImageLoader imageLoader = ImageLoader.getInstance(); 176 imgSmallXGray = imageLoader.getImage("smallx-gray"); 177 imgSmallX = imageLoader.getImage("smallx"); 178 179 lblX = new Label(cFilterArea, SWT.WRAP); 180 Messages.setLanguageTooltip(lblX, "MyTorrentsView.clearFilter.tooltip"); 181 lblX.setImage(imgSmallXGray); 182 lblX.addMouseListener(new MouseAdapter() { 183 public void mouseUp(MouseEvent e) { 184 txtFilter.setText(""); 185 } 186 }); 187 188 lblX.addDisposeListener(new DisposeListener() { 189 public void widgetDisposed(DisposeEvent arg0) { 190 ImageLoader imageLoader = ImageLoader.getInstance(); 191 imageLoader.releaseImage("smallx-gray"); 192 imageLoader.releaseImage("smallx"); 193 } 194 }); 195 196 Label lblSearch = new Label(cFilterArea, SWT.NONE); 197 imageLoader.setLabelImage(lblSearch, "search"); 198 199 tree = new Tree(cLeftSide, SWT.NONE); 200 FontData[] fontData = tree.getFont().getFontData(); 201 fontData[0].setStyle(SWT.BOLD); 202 filterFoundFont = new Font(d, fontData); 203 204 FormData formData; 205 206 formData = new FormData(); 207 formData.bottom = new FormAttachment(100, -5); 208 formData.left = new FormAttachment(0, 0); 209 formData.right = new FormAttachment(100, 0); 210 Utils.setLayoutData(cFilterArea, formData); 211 212 formData = new FormData(); 213 formData.top = new FormAttachment(0,5); 214 formData.left = new FormAttachment(0, 5); 215 Utils.setLayoutData(lblSearch, formData); 216 217 formData = new FormData(); 218 formData.top = new FormAttachment(0,5); 219 formData.left = new FormAttachment(lblSearch,5); 220 formData.right = new FormAttachment(lblX, -3); 221 Utils.setLayoutData(txtFilter, formData); 222 223 formData = new FormData(); 224 formData.top = new FormAttachment(0,5); 225 formData.right = new FormAttachment(100,-5); 226 Utils.setLayoutData(lblX, formData); 227 228 formData = new FormData(); 229 formData.top = new FormAttachment(0, 0); 230 formData.left = new FormAttachment(0,0); 231 formData.right = new FormAttachment(100,0); 232 formData.bottom = new FormAttachment(cFilterArea,-1); 233 Utils.setLayoutData(tree, formData); 234 235 Composite cRightSide = new Composite(form, SWT.NULL); 236 configLayout = new GridLayout(); 237 configLayout.marginHeight = 3; 238 configLayout.marginWidth = 0; 239 cRightSide.setLayout(configLayout); 240 241 // Header 242 243 Composite cHeader = new Composite(cRightSide, SWT.BORDER); 244 245 configLayout = new GridLayout(); 246 configLayout.marginHeight = 3; 247 configLayout.marginWidth = 0; 248 configLayout.numColumns = 2; 249 configLayout.marginRight = 5; 250 cHeader.setLayout(configLayout); 251 gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER); 252 Utils.setLayoutData(cHeader, gridData); 253 254 cHeader.setBackground(d.getSystemColor(SWT.COLOR_LIST_SELECTION)); 255 cHeader.setForeground(d.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT)); 256 257 lHeader = new Label(cHeader, SWT.NULL); 258 lHeader.setBackground(d.getSystemColor(SWT.COLOR_LIST_SELECTION)); 259 lHeader.setForeground(d.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT)); 260 fontData = lHeader.getFont().getFontData(); 261 fontData[0].setStyle(SWT.BOLD); 262 int fontHeight = (int)(fontData[0].getHeight() * 1.2); 263 fontData[0].setHeight(fontHeight); 264 headerFont = new Font(d, fontData); 265 lHeader.setFont(headerFont); 266 gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.HORIZONTAL_ALIGN_BEGINNING); 267 Utils.setLayoutData(lHeader, gridData); 268 269 270 usermodeHint = new Label(cHeader, SWT.NULL); 271 usermodeHint.setBackground(d.getSystemColor(SWT.COLOR_LIST_SELECTION)); 272 usermodeHint.setForeground(d.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT)); 273 gridData = new GridData(GridData.VERTICAL_ALIGN_CENTER | GridData.HORIZONTAL_ALIGN_END | GridData.GRAB_HORIZONTAL); 274 Utils.setLayoutData(usermodeHint, gridData); 275 276 Menu headerMenu = new Menu(cHeader.getShell(), SWT.POP_UP ); 277 278 final MenuItem menuShortCut = new MenuItem(headerMenu, SWT.PUSH); 279 Messages.setLanguageText( menuShortCut, "label.set.shortcut" ); 280 281 menuShortCut.addSelectionListener(new SelectionAdapter() { 282 public void widgetSelected(SelectionEvent e) { 283 284 final TreeItem tree_item = (TreeItem)lHeader.getData( "TreeItem" ); 285 286 if ( tree_item != null ){ 287 288 final String id = (String)tree_item.getData( "ID" ); 289 290 if ( id != null ){ 291 292 SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow( 293 "config.dialog.shortcut.title", 294 "config.dialog.shortcut.text"); 295 entryWindow.setPreenteredText(COConfigurationManager.getStringParameter( "config.section.shortcut.key." + id, "" ), false); 296 entryWindow.setTextLimit(1); 297 entryWindow.prompt(new UIInputReceiverListener() { 298 public void UIInputReceiverClosed(UIInputReceiver entryWindow) { 299 if (!entryWindow.hasSubmittedInput()) { 300 return; 301 } 302 String sReturn = entryWindow.getSubmittedInput(); 303 if ( sReturn != null ){ 304 305 sReturn = sReturn.trim(); 306 307 if ( sReturn.length() > 1 ){ 308 309 sReturn = sReturn.substring(0,1); 310 } 311 312 COConfigurationManager.setParameter( "config.section.shortcut.key." + id, sReturn ); 313 314 updateHeader( tree_item ); 315 } 316 } 317 }); 318 } 319 } 320 } 321 }); 322 323 cHeader.setMenu( headerMenu ); 324 lHeader.setMenu( headerMenu ); 325 usermodeHint.setMenu( headerMenu ); 326 327 // Config Section 328 cConfigSection = new Composite(cRightSide, SWT.NULL); 329 layoutConfigSection = new StackLayout(); 330 cConfigSection.setLayout(layoutConfigSection); 331 gridData = new GridData(GridData.FILL_BOTH); 332 gridData.horizontalIndent = 2; 333 Utils.setLayoutData(cConfigSection, gridData); 334 335 form.setWeights(new int[] {20,80}); 336 337 tree.addSelectionListener(new SelectionAdapter() { 338 public void widgetSelected(SelectionEvent e) { 339 Tree tree = (Tree)e.getSource(); 340 //Check that at least an item is selected 341 //OSX lets you select nothing in the tree for example when a child is selected 342 //and you close its parent. 343 if(tree.getSelection().length > 0) 344 showSection(tree.getSelection()[0], false); 345 } 346 }); 347 // Double click = expand/contract branch 348 tree.addListener(SWT.DefaultSelection, new Listener() { 349 public void handleEvent(Event e) { 350 TreeItem item = (TreeItem)e.item; 351 if (item != null) 352 item.setExpanded(!item.getExpanded()); 353 } 354 }); 355 } catch (Exception e) { 356 Logger.log(new LogEvent(LOGID, "Error initializing ConfigView", e)); 357 } 358 359 scResizeListener = new Listener() { 360 public void handleEvent(Event event) { 361 setupSC((ScrolledComposite)event.widget); 362 } 363 }; 364 365 366 // Add sections 367 /** How to add a new section 368 * 1) Create a new implementation of ConfigSectionSWT in a new file 369 * (Use the ConfigSectionTMP.java as a template if it's still around) 370 * 2) import it into here 371 * 3) add it to the internal sections list 372 */ 373 pluginSections = ConfigSectionRepository.getInstance().getList(); 374 375 ConfigSection[] internalSections = { 376 new ConfigSectionMode(), 377 new ConfigSectionStartShutdown(), 378 new ConfigSectionBackupRestore(), 379 new ConfigSectionConnection(), 380 new ConfigSectionConnectionProxy(), 381 new ConfigSectionConnectionAdvanced(), 382 new ConfigSectionConnectionEncryption(), 383 new ConfigSectionConnectionDNS(), 384 new ConfigSectionTransfer(), 385 new ConfigSectionTransferAutoSpeedSelect(), 386 new ConfigSectionTransferAutoSpeed(), 387 new ConfigSectionTransferAutoSpeedBeta(), 388 new ConfigSectionTransferLAN(), 389 new ConfigSectionFile(), 390 new ConfigSectionFileMove(), 391 new ConfigSectionFileTorrents(), 392 new ConfigSectionFileTorrentsDecoding(), 393 new ConfigSectionFilePerformance(), 394 new ConfigSectionInterface(), 395 new ConfigSectionInterfaceLanguage(), 396 new ConfigSectionInterfaceStart(), 397 new ConfigSectionInterfaceDisplay(), 398 new ConfigSectionInterfaceTables(), 399 new ConfigSectionInterfaceColor(), 400 new ConfigSectionInterfaceAlerts(), 401 new ConfigSectionInterfacePassword(), 402 new ConfigSectionInterfaceLegacy(), 403 new ConfigSectionIPFilter(), 404 new ConfigSectionPlugins(this), 405 new ConfigSectionStats(), 406 new ConfigSectionTracker(), 407 new ConfigSectionTrackerClient(), 408 new ConfigSectionTrackerServer(), 409 new ConfigSectionSecurity(), 410 new ConfigSectionSharing(), 411 new ConfigSectionLogging() 412 }; 413 414 pluginSections.addAll(0, Arrays.asList(internalSections)); 415 416 for (int i = 0; i < pluginSections.size(); i++) { 417 418 // slip the non-standard "plugins" initialisation inbetween the internal ones 419 // and the plugin ones so plugin ones can be children of it 420 421 boolean plugin_section = i >= internalSections.length; 422 423 ConfigSection section = pluginSections.get(i); 424 425 if ( section instanceof UISWTConfigSection ) { 426 String name; 427 try { 428 name = section.configSectionGetName(); 429 } catch (Exception e) { 430 Logger.log(new LogEvent(LOGID, "A ConfigSection plugin caused an " 431 + "error while trying to call its " 432 + "configSectionGetName function", e)); 433 name = "Bad Plugin"; 434 } 435 436 String section_key = name; 437 438 if ( plugin_section ){ 439 // if resource exists without prefix then use it as plugins don't 440 // need to start with the prefix 441 442 if ( !MessageText.keyExists(section_key)){ 443 444 section_key = sSectionPrefix + name; 445 } 446 447 }else{ 448 449 section_key = sSectionPrefix + name; 450 } 451 452 String section_name = MessageText.getString( section_key ); 453 454 try { 455 TreeItem treeItem; 456 String location = section.configSectionGetParentSection(); 457 458 if ( location.length() == 0 || location.equalsIgnoreCase(ConfigSection.SECTION_ROOT)){ 459 //int position = findInsertPointFor(section_name, tree); 460 //if ( position == -1 ){ 461 treeItem = new TreeItem(tree, SWT.NULL); 462 // }else{ 463 // treeItem = new TreeItem(tree, SWT.NULL, position); 464 //} 465 }else{ 466 TreeItem treeItemFound = findTreeItem(tree, location); 467 if (treeItemFound != null){ 468 if (location.equalsIgnoreCase(ConfigSection.SECTION_PLUGINS)) { 469 // Force ordering by name here. 470 int position = findInsertPointFor(section_name, treeItemFound); 471 if (position == -1) { 472 treeItem = new TreeItem(treeItemFound, SWT.NULL); 473 } 474 else { 475 treeItem = new TreeItem(treeItemFound, SWT.NULL, position); 476 } 477 } 478 else { 479 treeItem = new TreeItem(treeItemFound, SWT.NULL); 480 } 481 }else{ 482 treeItem = new TreeItem(tree, SWT.NULL); 483 } 484 } 485 486 ScrolledComposite sc = new ScrolledComposite(cConfigSection, SWT.H_SCROLL | SWT.V_SCROLL); 487 sc.setExpandHorizontal(true); 488 sc.setExpandVertical(true); 489 Utils.setLayoutData(sc, new GridData(GridData.FILL_BOTH)); 490 sc.getVerticalBar().setIncrement(16); 491 sc.addListener(SWT.Resize, scResizeListener); 492 493 if(i == 0) { 494 Composite c = ((UISWTConfigSection)section).configSectionCreate(sc); 495 sectionsCreated.add(section); 496 sc.setContent(c); 497 } 498 499 Messages.setLanguageText(treeItem, section_key); 500 treeItem.setData("Panel", sc); 501 treeItem.setData("ID", name); 502 treeItem.setData("ConfigSectionSWT", section); 503 504 sections.put(treeItem, section); 505 506 // ConfigSectionPlugins is special because it has to handle the 507 // PluginConfigModel config pages 508 if (section instanceof ConfigSectionPlugins) 509 ((ConfigSectionPlugins)section).initPluginSubSections(); 510 } catch (Exception e) { 511 Logger.log(new LogEvent(LOGID, "ConfigSection plugin '" + name 512 + "' caused an error", e)); 513 } 514 } 515 } 516 517 final Display d = composite.getDisplay(); 518 519 final Listener shortcut_listener = 520 new Listener() 521 { 522 public void 523 handleEvent( 524 Event e) 525 { 526 if ((e.stateMask & ( SWT.MOD1 | SWT.CONTROL )) != 0 || e.keyCode == SWT.COMMAND ){ 527 528 char key = e.character; 529 530 if (key <= 26 && key > 0){ 531 key += 'a' - 1; 532 } 533 534 if ((e.stateMask & SWT.SHIFT )!= 0 ){ 535 key = Character.toUpperCase(key); 536 } 537 if ( !Character.isISOControl( key )){ 538 539 for ( TreeItem ti: sections.keySet()){ 540 541 String id = (String)ti.getData( "ID" ); 542 543 if ( id != null ){ 544 545 String shortcut = COConfigurationManager.getStringParameter( "config.section.shortcut.key." + id, "" ); 546 547 if ( shortcut.equals( String.valueOf( key ))){ 548 549 //findFocus( cConfig ); 550 551 selectSection( id, true ); 552 553 e.doit = false; 554 555 break; 556 } 557 } 558 } 559 } 560 } 561 }; 562 }; 563 564 d.addFilter( SWT.KeyDown, shortcut_listener ); 565 566 cConfigSection.addDisposeListener( 567 new DisposeListener() { 568 569 public void widgetDisposed(DisposeEvent e) { 570 d.removeFilter( SWT.KeyDown, shortcut_listener); 571 } 572 }); 573 574 if (composite instanceof Shell) { 575 initApplyCloseButton(); 576 } else { 577 initSaveButton(); 578 } 579 580 if (startSection != null) { 581 if (selectSection(startSection,false)) { 582 return; 583 } 584 } 585 586 TreeItem selection = getLatestSelection(); 587 588 TreeItem[] items = { selection }; 589 590 tree.setSelection( items ); 591 592 // setSelection doesn't trigger a SelectionListener, so.. 593 594 showSection( selection, false ); 595 } 596 597 598 /* 599 private void 600 findFocus( 601 Control c ) 602 { 603 604 if ( c.isFocusControl()){ 605 System.out.println( "Focus=" + c ); 606 } 607 608 if ( c instanceof Composite ){ 609 610 Control[] kids = ((Composite)c).getChildren(); 611 612 for( Control k: kids ){ 613 614 findFocus( k ); 615 } 616 } 617 } 618 */ 619 setupSC(ScrolledComposite sc)620 private void setupSC(ScrolledComposite sc) { 621 Composite c = (Composite) sc.getContent(); 622 if (c != null) { 623 Point size1 = c.computeSize(sc.getClientArea().width, SWT.DEFAULT); 624 Point size = c.computeSize(SWT.DEFAULT, size1.y); 625 sc.setMinSize(size); 626 } 627 sc.getVerticalBar().setPageIncrement(sc.getSize().y); 628 } 629 630 631 /** 632 * @param text 633 */ filterTree(String text)634 protected void filterTree(String text) { 635 filterText = text; 636 if (filterDelayTimer != null) { 637 filterDelayTimer.destroy(); 638 } 639 640 if (lblX != null && !lblX.isDisposed()) { 641 Image img = filterText.length() > 0 ? imgSmallX : imgSmallXGray; 642 643 lblX.setImage(img); 644 } 645 646 647 filterDelayTimer = new Timer("Filter"); 648 filterDelayTimer.addEvent(SystemTime.getCurrentTime() + 300, 649 new TimerEventPerformer() { 650 public void perform(TimerEvent event) { 651 filterDelayTimer.destroy(); 652 filterDelayTimer = null; 653 654 Utils.execSWTThread(new AERunnable() { 655 public void runSupport() { 656 if (filterDelayTimer != null) { 657 return; 658 } 659 if ( tree.isDisposed()){ 660 return; 661 } 662 663 Shell shell = tree.getShell(); 664 if (shell != null) { 665 shell.setCursor(shell.getDisplay().getSystemCursor( 666 SWT.CURSOR_WAIT)); 667 } 668 try { 669 ArrayList<TreeItem> foundItems = new ArrayList<TreeItem>(); 670 TreeItem[] items = tree.getItems(); 671 try { 672 tree.setRedraw(false); 673 for (int i = 0; i < items.length; i++) { 674 items[i].setExpanded(false); 675 } 676 677 filterTree(items, filterText, foundItems); 678 } finally { 679 tree.setRedraw(true); 680 } 681 } finally { 682 if (shell != null) { 683 shell.setCursor(null); 684 } 685 TreeItem[] selection = tree.getSelection(); 686 if (selection != null && selection.length > 0) { 687 showSection(selection[0],false); 688 } 689 } 690 } 691 }); 692 } 693 }); 694 } 695 filterTree(TreeItem[] items, String text, ArrayList<TreeItem> foundItems)696 protected void filterTree(TreeItem[] items, String text, 697 ArrayList<TreeItem> foundItems) { 698 text = text.toLowerCase(); 699 for (int i = 0; i < items.length; i++) { 700 ensureSectionBuilt(items[i], false); 701 ScrolledComposite composite = (ScrolledComposite) items[i].getData("Panel"); 702 703 if (text.length() > 0 704 && (items[i].getText().toLowerCase().indexOf(text) >= 0 || compositeHasText( 705 composite, text))) { 706 foundItems.add(items[i]); 707 708 ensureExpandedTo(items[i]); 709 items[i].setFont(filterFoundFont); 710 } else { 711 items[i].setFont(null); 712 } 713 filterTree(items[i].getItems(), text, foundItems); 714 } 715 } 716 ensureExpandedTo(TreeItem item)717 private void ensureExpandedTo(TreeItem item) { 718 TreeItem itemParent = item.getParentItem(); 719 if (itemParent != null) { 720 itemParent.setExpanded(true); 721 ensureExpandedTo(itemParent); 722 } 723 } 724 725 /** 726 * @param composite 727 * @param text 728 * @return 729 */ compositeHasText(Composite composite, String text)730 private boolean compositeHasText(Composite composite, String text) { 731 Control[] children = composite.getChildren(); 732 733 for (int i = 0; i < children.length; i++) { 734 Control child = children[i]; 735 if (child instanceof Label) { 736 if (((Label)child).getText().toLowerCase().indexOf(text) >= 0) { 737 return true; 738 } 739 } else if (child instanceof Group) { 740 if (((Group)child).getText().toLowerCase().indexOf(text) >= 0) { 741 return true; 742 } 743 } else if (child instanceof Button) { 744 if (((Button)child).getText().toLowerCase().indexOf(text) >= 0) { 745 return true; 746 } 747 } else if (child instanceof List) { 748 String[] items = ((List)child).getItems(); 749 for (String item : items) { 750 if (item.toLowerCase().indexOf(text) >= 0) { 751 return true; 752 } 753 } 754 } else if (child instanceof Combo) { 755 String[] items = ((Combo)child).getItems(); 756 for (String item : items) { 757 if (item.toLowerCase().indexOf(text) >= 0) { 758 return true; 759 } 760 } 761 } 762 763 if (child instanceof Composite) { 764 if (compositeHasText((Composite) child, text)) { 765 return true; 766 } 767 } 768 } 769 770 return false; 771 } 772 773 private void saveLatestSelection( TreeItem item )774 saveLatestSelection( 775 TreeItem item ) 776 { 777 String path = ""; 778 779 while( item != null ){ 780 781 path = item.getText() + (path.length()==0?"":("$" + path )); 782 783 item = item.getParentItem(); 784 } 785 786 COConfigurationManager.setParameter( "ConfigView.section.last.selection", path ); 787 } 788 789 private TreeItem getLatestSelection()790 getLatestSelection() 791 { 792 String path = COConfigurationManager.getStringParameter( "ConfigView.section.last.selection", "" ); 793 794 String[] bits = path.split( "\\$" ); 795 796 TreeItem[] items = tree.getItems(); 797 798 TreeItem current = null; 799 800 boolean located = false; 801 802 for ( int i=0;i<bits.length;i++ ){ 803 804 String bit = bits[i]; 805 806 boolean found = false; 807 808 for ( int j=0;j<items.length;j++ ){ 809 810 if ( items[j].getText().equals( bit )){ 811 812 current = items[j]; 813 814 items = current.getItems(); 815 816 found = true; 817 818 if ( i == bits.length - 1 ){ 819 820 located = true; 821 } 822 823 break; 824 } 825 } 826 827 if ( !found ){ 828 829 break; 830 } 831 } 832 833 TreeItem result = located?current:tree.getItems()[0]; 834 835 return( result ); 836 } 837 838 private void showSection( TreeItem section, boolean focus )839 showSection( 840 TreeItem section, 841 boolean focus ) 842 { 843 saveLatestSelection( section ); 844 845 ScrolledComposite item = (ScrolledComposite)section.getData("Panel"); 846 847 if (item != null) { 848 849 ensureSectionBuilt(section, true); 850 851 layoutConfigSection.topControl = item; 852 853 setupSC(item); 854 855 if (filterText != null && filterText.length() > 0) { 856 hilightText(item, filterText); 857 item.layout(true, true); 858 } 859 860 cConfigSection.layout(); 861 862 updateHeader(section); 863 864 if ( focus ){ 865 layoutConfigSection.topControl.traverse( SWT.TRAVERSE_TAB_NEXT); 866 } 867 } 868 } 869 hilightText(Composite c, String text)870 private void hilightText(Composite c, String text) { 871 Control[] children = c.getChildren(); 872 for (Control child : children) { 873 if (child instanceof Composite) { 874 hilightText((Composite) child, text); 875 } 876 877 if (child instanceof Label) { 878 if (((Label)child).getText().toLowerCase().indexOf(text) >= 0) { 879 hilightControl(child); 880 } 881 } else if (child instanceof Group) { 882 if (((Group)child).getText().toLowerCase().indexOf(text) >= 0) { 883 hilightControl(child); 884 } 885 } else if (child instanceof Button) { 886 if (((Button)child).getText().toLowerCase().indexOf(text) >= 0) { 887 hilightControl(child); 888 } 889 } else if (child instanceof List) { 890 String[] items = ((List)child).getItems(); 891 for (String item : items) { 892 if (item.toLowerCase().indexOf(text) >= 0) { 893 hilightControl(child); 894 break; 895 } 896 } 897 } else if (child instanceof Combo) { 898 String[] items = ((Combo)child).getItems(); 899 for (String item : items) { 900 if (item.toLowerCase().indexOf(text) >= 0) { 901 hilightControl(child); 902 break; 903 } 904 } 905 } 906 907 } 908 } 909 910 /** 911 * @param child 912 * 913 * @since 4.5.1.1 914 */ hilightControl(Control child)915 private void hilightControl(Control child) { 916 child.setFont(headerFont); 917 child.setBackground(child.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND)); 918 child.setForeground(child.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND)); 919 } 920 ensureSectionBuilt(TreeItem treeSection, boolean recreateIfAlreadyThere)921 private void ensureSectionBuilt(TreeItem treeSection, boolean recreateIfAlreadyThere) { 922 ScrolledComposite item = (ScrolledComposite)treeSection.getData("Panel"); 923 924 if (item != null) { 925 926 ConfigSection configSection = (ConfigSection)treeSection.getData("ConfigSectionSWT"); 927 928 if (configSection != null) { 929 930 Control previous = item.getContent(); 931 if (previous instanceof Composite) { 932 if (!recreateIfAlreadyThere) { 933 return; 934 } 935 configSection.configSectionDelete(); 936 sectionsCreated.remove(configSection); 937 Utils.disposeComposite((Composite)previous,true); 938 } 939 940 Composite c = ((UISWTConfigSection)configSection).configSectionCreate(item); 941 942 sectionsCreated.add(configSection); 943 944 item.setContent(c); 945 } 946 } 947 } 948 updateHeader(TreeItem section)949 private void updateHeader(TreeItem section) { 950 if (section == null) 951 return; 952 953 lHeader.setData( "TreeItem", section ); 954 955 int userMode = COConfigurationManager.getIntParameter("User Mode"); 956 int maxUsermode = 0; 957 try 958 { 959 ConfigSection sect = sections.get(section); 960 if (sect instanceof UISWTConfigSection) 961 { 962 maxUsermode = ((UISWTConfigSection) sect).maxUserMode(); 963 } 964 } catch (Error e) 965 { 966 //Debug.printStackTrace(e); 967 } 968 969 String id = (String)section.getData( "ID" ); 970 971 String shortcut = COConfigurationManager.getStringParameter( "config.section.shortcut.key." + id, null ); 972 973 String sc_text; 974 975 if ( shortcut != null && shortcut.length() > 0 ){ 976 977 sc_text = " (Ctrl+" + shortcut.charAt(0) + ")"; 978 }else{ 979 980 sc_text = ""; 981 } 982 983 if (userMode < maxUsermode) 984 Messages.setLanguageText(usermodeHint, "ConfigView.higher.mode.available"); 985 else 986 usermodeHint.setText(""); 987 988 String sHeader = section.getText(); 989 990 section = section.getParentItem(); 991 while (section != null) 992 { 993 sHeader = section.getText() + " : " + sHeader; 994 section = section.getParentItem(); 995 } 996 lHeader.setText(" " + sHeader.replaceAll("&", "&&") + sc_text ); 997 lHeader.getParent().layout(true, true); 998 } 999 1000 createConfigSection(TreeItem treeItemParent, String sNameID, int position, boolean bPrefix)1001 public Composite createConfigSection(TreeItem treeItemParent, 1002 String sNameID, 1003 int position, 1004 boolean bPrefix) { 1005 ScrolledComposite sc = new ScrolledComposite(cConfigSection, SWT.H_SCROLL | SWT.V_SCROLL); 1006 sc.setExpandHorizontal(true); 1007 sc.setExpandVertical(true); 1008 Utils.setLayoutData(sc, new GridData(GridData.FILL_BOTH)); 1009 sc.getVerticalBar().setIncrement(16); 1010 sc.addListener(SWT.Resize, scResizeListener); 1011 1012 Composite cConfigSection = new Composite(sc, SWT.NULL); 1013 1014 String section_key = ((bPrefix) ? sSectionPrefix : "") + sNameID; 1015 1016 if (position == -2) { // Means "auto-order". 1017 position = findInsertPointFor(MessageText.getString(section_key), (treeItemParent == null) ? (Object)tree : (Object)treeItemParent); 1018 } 1019 1020 TreeItem treeItem; 1021 if (treeItemParent == null) { 1022 if (position >= 0) 1023 treeItem = new TreeItem(tree, SWT.NULL, position); 1024 else 1025 treeItem = new TreeItem(tree, SWT.NULL); 1026 } else { 1027 if (position >= 0) 1028 treeItem = new TreeItem(treeItemParent, SWT.NULL, position); 1029 else 1030 treeItem = new TreeItem(treeItemParent, SWT.NULL); 1031 } 1032 Messages.setLanguageText(treeItem, section_key); 1033 treeItem.setData("Panel", sc); 1034 treeItem.setData("ID", sNameID); 1035 1036 sc.setContent(cConfigSection); 1037 return cConfigSection; 1038 } 1039 1040 private static Comparator<Object> insert_point_comparator = new Comparator<Object>() { 1041 1042 private String asString(Object o) { 1043 if (o instanceof String) { 1044 return (String)o; 1045 } 1046 else if (o instanceof TreeItem) { 1047 return ((TreeItem)o).getText(); 1048 } 1049 else { 1050 throw new ClassCastException("object is not String or TreeItem: " + o.getClass().getName()); 1051 } 1052 } 1053 1054 public int compare(Object o1, Object o2) { 1055 int result = String.CASE_INSENSITIVE_ORDER.compare(asString(o1), asString(o2)); 1056 return result; 1057 } 1058 }; 1059 findInsertPointFor(String name, Object structure)1060 private static int findInsertPointFor(String name, Object structure) { 1061 TreeItem[] children = null; 1062 if (structure instanceof Tree) { 1063 children = ((Tree)structure).getItems(); 1064 } 1065 else { 1066 children = ((TreeItem)structure).getItems(); 1067 } 1068 if (children.length == 0) {return -1;} 1069 int result = Arrays.binarySearch(children, name, insert_point_comparator); 1070 if (result > 0) {return result;} 1071 result = -(result+1); 1072 if (result == children.length) { 1073 result = -1; 1074 } 1075 return result; 1076 } 1077 findTreeItem(String ID)1078 public TreeItem findTreeItem(String ID) { 1079 return findTreeItem((Tree)null, ID); 1080 } 1081 findTreeItem(Tree tree, String ID)1082 private TreeItem findTreeItem(Tree tree, String ID) { 1083 if (tree == null) { 1084 tree = this.tree; 1085 } 1086 if (tree == null) { 1087 return null; 1088 } 1089 TreeItem[] items = tree.getItems(); 1090 for (int i = 0; i < items.length; i++) { 1091 String itemID = (String)items[i].getData("ID"); 1092 if (itemID != null && itemID.equalsIgnoreCase(ID)) { 1093 return items[i]; 1094 } 1095 TreeItem itemFound = findTreeItem(items[i], ID); 1096 if (itemFound != null) 1097 return itemFound; 1098 } 1099 return null; 1100 } 1101 findTreeItem(TreeItem item, String ID)1102 private TreeItem findTreeItem(TreeItem item, String ID) { 1103 TreeItem[] subItems = item.getItems(); 1104 for (int i = 0; i < subItems.length; i++) { 1105 String itemID = (String)subItems[i].getData("ID"); 1106 if (itemID != null && itemID.equalsIgnoreCase(ID)) { 1107 return subItems[i]; 1108 } 1109 1110 TreeItem itemFound = findTreeItem(subItems[i], ID); 1111 if (itemFound != null) 1112 return itemFound; 1113 } 1114 return null; 1115 } 1116 initSaveButton()1117 private void initSaveButton() { 1118 GridData gridData; 1119 final Button save = new Button(cConfig, SWT.PUSH); 1120 Messages.setLanguageText(save, "ConfigView.button.save"); //$NON-NLS-1$ 1121 gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); 1122 gridData.horizontalSpan = 2; 1123 gridData.widthHint = 80; 1124 Utils.setLayoutData(save, gridData); 1125 1126 save.addSelectionListener(new SelectionAdapter() { 1127 public void widgetSelected(SelectionEvent event) { 1128 // force focusout on osx 1129 save.setFocus(); 1130 save(); 1131 } 1132 }); 1133 } 1134 initApplyCloseButton()1135 private void initApplyCloseButton() { 1136 Composite cButtons = new Composite(cConfig, SWT.NONE); 1137 GridLayout gridLayout = new GridLayout(); 1138 gridLayout.horizontalSpacing = gridLayout.verticalSpacing = gridLayout.marginHeight = gridLayout.marginWidth = 0; 1139 gridLayout.numColumns = 2; 1140 cButtons.setLayout(gridLayout); 1141 Utils.setLayoutData(cButtons, new GridData(GridData.HORIZONTAL_ALIGN_END)); 1142 1143 GridData gridData; 1144 final Button apply = new Button(cButtons, SWT.PUSH); 1145 Messages.setLanguageText(apply, "Button.apply"); 1146 gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); 1147 gridData.widthHint = 80; 1148 Utils.setLayoutData(apply, gridData); 1149 1150 apply.addSelectionListener(new SelectionAdapter() { 1151 public void widgetSelected(SelectionEvent event) { 1152 // force focusout on osx 1153 apply.setFocus(); 1154 save(); 1155 } 1156 }); 1157 1158 final Button close = new Button(cButtons, SWT.PUSH); 1159 Messages.setLanguageText(close, "Button.close"); 1160 gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); 1161 gridData.widthHint = 80; 1162 Utils.setLayoutData(close, gridData); 1163 1164 close.addSelectionListener(new SelectionAdapter() { 1165 public void widgetSelected(SelectionEvent event) { 1166 // force focusout on osx 1167 apply.setFocus(); 1168 save(); 1169 apply.getShell().dispose(); 1170 } 1171 }); 1172 } 1173 getComposite()1174 private Composite getComposite() { 1175 return cConfig; 1176 } 1177 updateLanguage()1178 private void updateLanguage() { 1179 updateHeader(tree.getSelection()[0]); 1180 if (swtView != null) { 1181 swtView.setTitle(getFullTitle()); 1182 } 1183 // cConfig.setSize(cConfig.computeSize(SWT.DEFAULT, SWT.DEFAULT)); 1184 } 1185 delete()1186 private void delete() { 1187 for (ConfigSection section : sectionsCreated) { 1188 try { 1189 section.configSectionDelete(); 1190 } catch (Exception e) { 1191 Debug.out("Error while deleting config section", e); 1192 } 1193 } 1194 sectionsCreated.clear(); 1195 if ( pluginSections != null ){ 1196 pluginSections.clear(); 1197 } 1198 if ( tree != null ){ 1199 if(! tree.isDisposed()) { 1200 TreeItem[] items = tree.getItems(); 1201 for (int i = 0; i < items.length; i++) { 1202 Composite c = (Composite)items[i].getData("Panel"); 1203 Utils.disposeComposite(c); 1204 items[i].setData("Panel", null); 1205 1206 items[i].setData("ConfigSectionSWT", null); 1207 } 1208 } 1209 } 1210 Utils.disposeComposite(cConfig); 1211 1212 Utils.disposeSWTObjects(new Object[] { headerFont, filterFoundFont }); 1213 headerFont = null; 1214 filterFoundFont = null; 1215 } 1216 getFullTitle()1217 private String getFullTitle() { 1218 /* 1219 * Using resolveLocalizationKey because there are different version for Classic vs. Vuze 1220 */ 1221 return MessageText.getString(MessageText.resolveLocalizationKey("ConfigView.title.full")); //$NON-NLS-1$ 1222 } 1223 selectSection(String id, boolean focus)1224 public boolean selectSection(String id, boolean focus) { 1225 TreeItem ti = findTreeItem(id); 1226 if (ti == null) 1227 return false; 1228 tree.setSelection(new TreeItem[] { ti }); 1229 showSection(ti, focus); 1230 return true; 1231 } 1232 1233 public void selectSection( Class<?> config_section_class )1234 selectSection( 1235 Class<?> config_section_class ) 1236 { 1237 TreeItem[] items = tree.getItems(); 1238 1239 for (int i=0;i<items.length;i++){ 1240 1241 TreeItem item = items[i]; 1242 1243 ConfigSection section = (ConfigSection)item.getData("ConfigSectionSWT"); 1244 1245 if ( section != null && section.getClass() == config_section_class ){ 1246 1247 tree.setSelection( new TreeItem[]{ item }); 1248 1249 showSection( item, true ); 1250 1251 break; 1252 } 1253 } 1254 } 1255 save()1256 public void save() { 1257 COConfigurationManager.setParameter("updated", 1); 1258 COConfigurationManager.save(); 1259 1260 if (null != pluginSections) { 1261 for (int i = 0; i < pluginSections.size(); i++) { 1262 pluginSections.get(i).configSectionSave(); 1263 } 1264 } 1265 } 1266 dataSourceChanged(Object newDataSource)1267 private void dataSourceChanged(Object newDataSource) { 1268 1269 if (newDataSource instanceof String) { 1270 String id = (String) newDataSource; 1271 startSection = id; 1272 Utils.execSWTThread(new AERunnable() { 1273 public void runSupport() { 1274 selectSection(startSection,false); 1275 } 1276 }); 1277 } 1278 } 1279 eventOccurred(UISWTViewEvent event)1280 public boolean eventOccurred(UISWTViewEvent event) { 1281 switch (event.getType()) { 1282 case UISWTViewEvent.TYPE_CREATE: 1283 swtView = (UISWTView)event.getData(); 1284 swtView.setTitle(getFullTitle()); 1285 break; 1286 1287 case UISWTViewEvent.TYPE_DESTROY: 1288 delete(); 1289 break; 1290 1291 case UISWTViewEvent.TYPE_INITIALIZE: 1292 initialize((Composite)event.getData()); 1293 break; 1294 1295 case UISWTViewEvent.TYPE_LANGUAGEUPDATE: 1296 Messages.updateLanguageForControl(getComposite()); 1297 updateLanguage(); 1298 break; 1299 1300 case UISWTViewEvent.TYPE_DATASOURCE_CHANGED: 1301 dataSourceChanged(event.getData()); 1302 break; 1303 1304 case UISWTViewEvent.TYPE_FOCUSGAINED: 1305 break; 1306 1307 case UISWTViewEvent.TYPE_REFRESH: 1308 break; 1309 } 1310 1311 return true; 1312 } 1313 1314 } 1315