2
* Created on 2 juil. 2003
3
* Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
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.
17
* AELITIS, SAS au capital de 46,603.30 euros
18
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
21
package org.gudy.azureus2.ui.swt.views;
23
import java.util.ArrayList;
24
import java.util.Arrays;
25
import java.util.Comparator;
27
import org.eclipse.swt.SWT;
28
import org.eclipse.swt.custom.SashForm;
29
import org.eclipse.swt.custom.ScrolledComposite;
30
import org.eclipse.swt.custom.StackLayout;
31
import org.eclipse.swt.events.*;
32
import org.eclipse.swt.graphics.Font;
33
import org.eclipse.swt.graphics.FontData;
34
import org.eclipse.swt.graphics.Image;
35
import org.eclipse.swt.layout.*;
36
import org.eclipse.swt.widgets.*;
38
import org.gudy.azureus2.core3.config.COConfigurationManager;
39
import org.gudy.azureus2.core3.internat.MessageText;
40
import org.gudy.azureus2.core3.logging.LogEvent;
41
import org.gudy.azureus2.core3.logging.LogIDs;
42
import org.gudy.azureus2.core3.logging.Logger;
43
import org.gudy.azureus2.core3.util.*;
44
import org.gudy.azureus2.pluginsimpl.local.ui.config.ConfigSectionRepository;
45
import org.gudy.azureus2.ui.swt.ImageRepository;
46
import org.gudy.azureus2.ui.swt.Messages;
47
import org.gudy.azureus2.ui.swt.Utils;
48
import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection;
49
import org.gudy.azureus2.ui.swt.views.configsections.*;
51
import com.aelitis.azureus.core.AzureusCore;
53
import org.gudy.azureus2.plugins.ui.config.ConfigSection;
54
import org.gudy.azureus2.plugins.ui.config.ConfigSectionSWT;
60
public class ConfigView extends AbstractIView {
61
private static final LogIDs LOGID = LogIDs.GUI;
62
public static final String sSectionPrefix = "ConfigView.section.";
64
AzureusCore azureus_core;
67
Composite cConfigSection;
68
StackLayout layoutConfigSection;
73
ArrayList pluginSections;
75
private Timer filterDelayTimer;
76
private String filterText = "";
82
* @param _azureus_core
86
AzureusCore _azureus_core )
88
azureus_core = _azureus_core;
92
* @see org.gudy.azureus2.ui.swt.IView#initialize(org.eclipse.swt.widgets.Composite)
94
public void initialize(Composite composite) {
97
/--cConfig-----------------------------------------------------------\
98
| ###SashForm#form################################################## |
99
| # /--cLeftSide-\ /--cRightSide---------------------------------\ # |
100
| # |txtFilter X | | ***cHeader********************************* | # |
101
| # | ##tree#### | | * lHeader * | # |
102
| # | # # | | ******************************************* | # |
103
| # | # # | | ###Composite cConfigSection################ | # |
104
| # | # # | | # # | # |
105
| # | # # | | # # | # |
106
| # | # # | | # # | # |
107
| # | # # | | # # | # |
108
| # | ########## | | ########################################### | # |
109
| # \------------/ \---------------------------------------------/ # |
110
| ################################################################## |
112
\--------------------------------------------------------------------/
115
Display d = composite.getDisplay();
117
cConfig = new Composite(composite, SWT.NONE);
118
GridLayout configLayout = new GridLayout();
119
configLayout.marginHeight = 0;
120
configLayout.marginWidth = 0;
121
cConfig.setLayout(configLayout);
122
gridData = new GridData(GridData.FILL_BOTH);
123
cConfig.setLayoutData(gridData);
125
SashForm form = new SashForm(cConfig,SWT.HORIZONTAL);
126
gridData = new GridData(GridData.FILL_BOTH);
127
form.setLayoutData(gridData);
129
Composite cLeftSide = new Composite(form, SWT.BORDER);
130
gridData = new GridData(GridData.FILL_BOTH);
131
cLeftSide.setLayoutData(gridData);
133
FormLayout layout = new FormLayout();
134
cLeftSide.setLayout(layout);
136
final Text txtFilter = new Text(cLeftSide, SWT.BORDER);
137
final String sFilterText = MessageText.getString("ConfigView.filter");
138
txtFilter.setText(sFilterText);
139
txtFilter.selectAll();
140
txtFilter.addModifyListener(new ModifyListener() {
141
public void modifyText(ModifyEvent e) {
142
filterTree(txtFilter.getText());
145
txtFilter.addMouseListener(new MouseAdapter() {
146
public void mouseDown(MouseEvent e) {
147
if (txtFilter.getText().equals(sFilterText)) {
148
txtFilter.selectAll();
152
txtFilter.setFocus();
154
lblX = new Label(cLeftSide, SWT.WRAP);
155
Messages.setLanguageTooltip(lblX, "MyTorrentsView.clearFilter.tooltip");
156
lblX.setImage(ImageRepository.getImage("smallx-gray"));
157
lblX.addMouseListener(new MouseAdapter() {
158
public void mouseUp(MouseEvent e) {
159
txtFilter.setText("");
163
tree = new Tree(cLeftSide, SWT.NONE);
164
FontData[] fontData = tree.getFont().getFontData();
165
fontData[0].setStyle(SWT.BOLD);
166
filterFoundFont = new Font(d, fontData);
168
cLeftSide.setBackground(tree.getBackground());
169
lblX.setBackground(tree.getBackground());
172
formData = new FormData();
173
formData.top = new FormAttachment(0,5);
174
formData.left = new FormAttachment(0,5);
175
formData.right = new FormAttachment(lblX, -3);
176
txtFilter.setLayoutData(formData);
178
formData = new FormData();
179
formData.top = new FormAttachment(0,5);
180
formData.right = new FormAttachment(100,-5);
181
lblX.setLayoutData(formData);
183
formData = new FormData();
184
formData.top = new FormAttachment(txtFilter,5);
185
formData.left = new FormAttachment(0,0);
186
formData.right = new FormAttachment(100,0);
187
formData.bottom = new FormAttachment(100,0);
188
tree.setLayoutData(formData);
190
Composite cRightSide = new Composite(form, SWT.NULL);
191
configLayout = new GridLayout();
192
configLayout.marginHeight = 3;
193
configLayout.marginWidth = 0;
194
cRightSide.setLayout(configLayout);
197
Composite cHeader = new Composite(cRightSide, SWT.BORDER);
198
configLayout = new GridLayout();
199
configLayout.marginHeight = 3;
200
configLayout.marginWidth = 0;
201
cHeader.setLayout(configLayout);
202
gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER);
203
cHeader.setLayoutData(gridData);
205
cHeader.setBackground(d.getSystemColor(SWT.COLOR_LIST_SELECTION));
206
cHeader.setForeground(d.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT));
208
lHeader = new Label(cHeader, SWT.NULL);
209
lHeader.setBackground(d.getSystemColor(SWT.COLOR_LIST_SELECTION));
210
lHeader.setForeground(d.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT));
211
fontData = lHeader.getFont().getFontData();
212
fontData[0].setStyle(SWT.BOLD);
213
int fontHeight = (int)(fontData[0].getHeight() * 1.2);
214
fontData[0].setHeight(fontHeight);
215
headerFont = new Font(d, fontData);
216
lHeader.setFont(headerFont);
217
gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER);
218
lHeader.setLayoutData(gridData);
221
cConfigSection = new Composite(cRightSide, SWT.NULL);
222
layoutConfigSection = new StackLayout();
223
cConfigSection.setLayout(layoutConfigSection);
224
gridData = new GridData(GridData.FILL_BOTH);
225
cConfigSection.setLayoutData(gridData);
228
form.setWeights(new int[] {20,80});
230
tree.addSelectionListener(new SelectionAdapter() {
231
public void widgetSelected(SelectionEvent e) {
232
Tree tree = (Tree)e.getSource();
233
//Check that at least an item is selected
234
//OSX lets you select nothing in the tree for example when a child is selected
235
//and you close its parent.
236
if(tree.getSelection().length > 0)
237
showSection(tree.getSelection()[0]);
240
// Double click = expand/contract branch
241
tree.addListener(SWT.DefaultSelection, new Listener() {
242
public void handleEvent(Event e) {
243
TreeItem item = (TreeItem)e.item;
245
item.setExpanded(!item.getExpanded());
248
} catch (Exception e) {
249
Logger.log(new LogEvent(LOGID, "Error initializing ConfigView", e));
255
/** How to add a new section
256
* 1) Create a new implementation of ConfigSectionSWT in a new file
257
* (Use the ConfigSectionTMP.java as a template if it's still around)
258
* 2) import it into here
259
* 3) add it to the internal sections list
261
pluginSections = ConfigSectionRepository.getInstance().getList();
263
ConfigSection[] internalSections = { new ConfigSectionConnection(),
264
new ConfigSectionConnectionProxy(),
265
new ConfigSectionConnectionAdvanced(),
266
new ConfigSectionConnectionEncryption(),
267
new ConfigSectionTransfer(azureus_core),
268
new ConfigSectionTransferAutoSpeed(),
269
new ConfigSectionTransferLAN(),
270
new ConfigSectionFile(),
271
new ConfigSectionFileMove(),
272
new ConfigSectionFileTorrents(),
273
new ConfigSectionFileTorrentsDecoding(),
274
new ConfigSectionFilePerformance(),
275
new ConfigSectionInterface(),
276
new ConfigSectionInterfaceLanguage(),
277
new ConfigSectionInterfaceStart(),
278
new ConfigSectionInterfaceDisplay(),
279
new ConfigSectionInterfaceColor(),
280
new ConfigSectionInterfaceAlerts(),
281
new ConfigSectionMode(),
282
new ConfigSectionIPFilter(azureus_core),
283
new ConfigSectionPlugins(this, azureus_core),
284
new ConfigSectionStats(),
285
new ConfigSectionTracker(azureus_core),
286
new ConfigSectionTrackerClient(),
287
new ConfigSectionTrackerServer(azureus_core),
288
new ConfigSectionSecurity(),
289
new ConfigSectionSharing(),
290
new ConfigSectionLogging()
293
pluginSections.addAll(0, Arrays.asList(internalSections));
295
for (int i = 0; i < pluginSections.size(); i++) {
297
// slip the non-standard "plugins" initialisation inbetween the internal ones
298
// and the plugin ones so plugin ones can be children of it
300
boolean plugin_section = i >= internalSections.length;
302
ConfigSection section = (ConfigSection)pluginSections.get(i);
304
if (section instanceof ConfigSectionSWT || section instanceof UISWTConfigSection ) {
307
name = section.configSectionGetName();
308
} catch (Exception e) {
309
Logger.log(new LogEvent(LOGID, "A ConfigSection plugin caused an "
310
+ "error while trying to call its "
311
+ "configSectionGetName function", e));
315
String section_key = name;
317
if ( plugin_section ){
318
// if resource exists without prefix then use it as plugins don't
319
// need to start with the prefix
321
if ( !MessageText.keyExists(section_key)){
323
section_key = sSectionPrefix + name;
328
section_key = sSectionPrefix + name;
333
String location = section.configSectionGetParentSection();
335
if (location.equalsIgnoreCase(ConfigSection.SECTION_ROOT))
336
treeItem = new TreeItem(tree, SWT.NULL);
337
else if (location != "") {
338
TreeItem treeItemFound = findTreeItem(tree, location);
339
if (treeItemFound != null){
340
if (location.equalsIgnoreCase(ConfigSection.SECTION_PLUGINS)) {
341
// Force ordering by name here.
342
int position = findInsertPointFor(MessageText.getString(section_key), treeItemFound);
343
if (position == -1) {
344
treeItem = new TreeItem(treeItemFound, SWT.NULL);
347
treeItem = new TreeItem(treeItemFound, SWT.NULL, position);
351
treeItem = new TreeItem(treeItemFound, SWT.NULL);
354
treeItem = new TreeItem(tree, SWT.NULL);
357
treeItem = new TreeItem(tree, SWT.NULL);
360
ScrolledComposite sc = new ScrolledComposite(cConfigSection, SWT.H_SCROLL | SWT.V_SCROLL);
361
sc.setExpandHorizontal(true);
362
sc.setExpandVertical(true);
363
sc.setLayoutData(new GridData(GridData.FILL_BOTH));
364
sc.getVerticalBar().setIncrement(16);
365
sc.addListener(SWT.Resize, new Listener() {
366
public void handleEvent(Event event) {
367
ScrolledComposite sc = (ScrolledComposite)event.widget;
368
sc.getVerticalBar().setPageIncrement(sc.getSize().y);
374
if ( section instanceof ConfigSectionSWT ){
376
c = ((ConfigSectionSWT)section).configSectionCreate(sc);
380
c = ((UISWTConfigSection)section).configSectionCreate(sc);
385
Messages.setLanguageText(treeItem, section_key);
386
treeItem.setData("Panel", sc);
387
treeItem.setData("ID", name);
388
treeItem.setData("ConfigSectionSWT", section);
390
// ConfigSectionPlugins is special because it has to handle the
391
// PluginConfigModel config pages
392
if (section instanceof ConfigSectionPlugins)
393
((ConfigSectionPlugins)section).initPluginSubSections();
394
} catch (Exception e) {
395
Logger.log(new LogEvent(LOGID, "ConfigSection plugin '" + name
396
+ "' caused an error", e));
406
TreeItem[] items = { tree.getItems()[0] };
407
tree.setSelection(items);
408
// setSelection doesn't trigger a SelectionListener, so..
409
showSection(items[0]);
415
protected void filterTree(String text) {
417
if (filterDelayTimer != null) {
418
filterDelayTimer.destroy();
421
if (lblX != null && !lblX.isDisposed()) {
422
Image img = ImageRepository.getImage(filterText.length() > 0 ? "smallx"
429
filterDelayTimer = new Timer("Filter");
430
filterDelayTimer.addEvent(SystemTime.getCurrentTime() + 300,
431
new TimerEventPerformer() {
432
public void perform(TimerEvent event) {
433
filterDelayTimer.destroy();
434
filterDelayTimer = null;
436
Utils.execSWTThread(new AERunnable() {
437
public void runSupport() {
438
// TODO Auto-generated method stub
439
ArrayList foundItems = new ArrayList();
440
TreeItem[] items = tree.getItems();
442
tree.setRedraw(false);
443
for (int i = 0; i < items.length; i++) {
444
items[i].setExpanded(false);
447
filterTree(items, filterText, foundItems);
449
tree.setRedraw(true);
457
protected void filterTree(TreeItem[] items, String text, ArrayList foundItems)
459
text = text.toLowerCase();
460
for (int i = 0; i < items.length; i++) {
461
ensureSectionBuilt(items[i]);
462
ScrolledComposite composite = (ScrolledComposite) items[i].getData("Panel");
464
if (text.length() > 0
465
&& (items[i].getText().toLowerCase().indexOf(text) >= 0 || compositeHasText(
467
foundItems.add(items[i]);
469
ensureExpandedTo(items[i]);
470
items[i].setFont(filterFoundFont);
472
items[i].setFont(null);
474
filterTree(items[i].getItems(), text, foundItems);
478
private void ensureExpandedTo(TreeItem item) {
479
TreeItem itemParent = item.getParentItem();
480
if (itemParent != null) {
481
itemParent.setExpanded(true);
482
ensureExpandedTo(itemParent);
491
private boolean compositeHasText(Composite composite, String text) {
492
Control[] children = composite.getChildren();
494
for (int i = 0; i < children.length; i++) {
495
Control child = children[i];
496
if (child instanceof Label) {
497
if (((Label)child).getText().toLowerCase().indexOf(text) >= 0) {
500
} else if (child instanceof Group) {
501
if (((Group)child).getText().toLowerCase().indexOf(text) >= 0) {
504
} else if (child instanceof Button) {
505
if (((Button)child).getText().toLowerCase().indexOf(text) >= 0) {
510
if (child instanceof Composite) {
511
if (compositeHasText((Composite) child, text)) {
520
private void showSection(TreeItem section) {
521
ScrolledComposite item = (ScrolledComposite)section.getData("Panel");
525
ensureSectionBuilt(section);
527
layoutConfigSection.topControl = item;
529
Composite c = (Composite)item.getContent();
531
item.setMinSize(c.computeSize(SWT.DEFAULT, SWT.DEFAULT));
532
cConfigSection.layout();
534
updateHeader(section);
538
private void ensureSectionBuilt(TreeItem section) {
539
ScrolledComposite item = (ScrolledComposite)section.getData("Panel");
543
ConfigSection configSection = (ConfigSection)section.getData("ConfigSectionSWT");
545
if (configSection != null) {
547
Control previous = item.getContent();
548
if (previous instanceof Composite) {
549
configSection.configSectionDelete();
550
Utils.disposeComposite((Composite)previous,true);
555
if ( configSection instanceof ConfigSectionSWT ){
557
c = ((ConfigSectionSWT)configSection).configSectionCreate(item);
561
c = ((UISWTConfigSection)configSection).configSectionCreate(item);
569
private void updateHeader(TreeItem section) {
573
String sHeader = section.getText();
574
section = section.getParentItem();
575
while (section != null) {
576
sHeader = section.getText() + " : " + sHeader;
577
section = section.getParentItem();
579
lHeader.setText(" " + sHeader.replaceAll("&", "&&"));
583
private Composite createConfigSection(String sNameID) {
584
return createConfigSection(null, sNameID, -1, true);
587
private Composite createConfigSection(String sNameID, int position) {
588
return createConfigSection(null, sNameID, position, true);
591
public Composite createConfigSection(TreeItem treeItemParent,
595
ScrolledComposite sc = new ScrolledComposite(cConfigSection, SWT.H_SCROLL | SWT.V_SCROLL);
596
sc.setExpandHorizontal(true);
597
sc.setExpandVertical(true);
598
sc.setLayoutData(new GridData(GridData.FILL_BOTH));
599
sc.getVerticalBar().setIncrement(16);
600
sc.addListener(SWT.Resize, new Listener() {
601
public void handleEvent(Event event) {
602
ScrolledComposite sc = (ScrolledComposite)event.widget;
603
sc.getVerticalBar().setPageIncrement(sc.getSize().y);
607
Composite cConfigSection = new Composite(sc, SWT.NULL);
609
String section_key = ((bPrefix) ? sSectionPrefix : "") + sNameID;
611
if (position == -2) { // Means "auto-order".
612
position = findInsertPointFor(MessageText.getString(section_key), (treeItemParent == null) ? (Object)tree : (Object)treeItemParent);
616
if (treeItemParent == null) {
618
treeItem = new TreeItem(tree, SWT.NULL, position);
620
treeItem = new TreeItem(tree, SWT.NULL);
623
treeItem = new TreeItem(treeItemParent, SWT.NULL, position);
625
treeItem = new TreeItem(treeItemParent, SWT.NULL);
627
Messages.setLanguageText(treeItem, section_key);
628
treeItem.setData("Panel", sc);
629
treeItem.setData("ID", sNameID);
631
sc.setContent(cConfigSection);
632
return cConfigSection;
635
private static Comparator insert_point_comparator = new Comparator() {
637
private String asString(Object o) {
638
if (o instanceof String) {
641
else if (o instanceof TreeItem) {
642
return ((TreeItem)o).getText();
645
throw new ClassCastException("object is not String or TreeItem: " + o.getClass().getName());
649
public int compare(Object o1, Object o2) {
650
int result = String.CASE_INSENSITIVE_ORDER.compare(asString(o1), asString(o2));
655
public static int findInsertPointFor(String name, Object structure) {
656
TreeItem[] children = null;
657
if (structure instanceof Tree) {
658
children = ((Tree)structure).getItems();
661
children = ((TreeItem)structure).getItems();
663
if (children.length == 0) {return -1;}
664
int result = Arrays.binarySearch(children, name, insert_point_comparator);
665
if (result > 0) {return result;}
666
result = -(result+1);
667
if (result == children.length) {
673
public TreeItem findTreeItem(String ID) {
674
return findTreeItem((Tree)null, ID);
677
private TreeItem findTreeItem(Tree tree, String ID) {
680
TreeItem[] items = tree.getItems();
681
for (int i = 0; i < items.length; i++) {
682
String itemID = (String)items[i].getData("ID");
683
if (itemID != null && itemID.equalsIgnoreCase(ID)) {
686
TreeItem itemFound = findTreeItem(items[i], ID);
687
if (itemFound != null)
693
private TreeItem findTreeItem(TreeItem item, String ID) {
694
TreeItem[] subItems = item.getItems();
695
for (int i = 0; i < subItems.length; i++) {
696
String itemID = (String)subItems[i].getData("ID");
697
if (itemID != null && itemID.equalsIgnoreCase(ID)) {
701
TreeItem itemFound = findTreeItem(subItems[i], ID);
702
if (itemFound != null)
708
private void initSaveButton() {
710
final Button save = new Button(cConfig, SWT.PUSH);
711
Messages.setLanguageText(save, "ConfigView.button.save"); //$NON-NLS-1$
712
gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
713
gridData.horizontalSpan = 2;
714
gridData.widthHint = 80;
715
save.setLayoutData(gridData);
717
save.addSelectionListener(new SelectionAdapter() {
718
public void widgetSelected(SelectionEvent event) {
719
// force focusout on osx
721
COConfigurationManager.setParameter("updated", 1);
722
COConfigurationManager.save();
724
for (int i = 0; i < pluginSections.size(); i++)
725
((ConfigSection) pluginSections.get(i)).configSectionSave();
731
* @see org.gudy.azureus2.ui.swt.IView#getComposite()
733
public Composite getComposite() {
737
public void updateLanguage() {
738
super.updateLanguage();
739
updateHeader(tree.getSelection()[0]);
740
// cConfig.setSize(cConfig.computeSize(SWT.DEFAULT, SWT.DEFAULT));
743
public void delete() {
744
for (int i = 0; i < pluginSections.size(); i++)
745
((ConfigSection)pluginSections.get(i)).configSectionDelete();
746
pluginSections.clear();
747
if(! tree.isDisposed()) {
748
TreeItem[] items = tree.getItems();
749
for (int i = 0; i < items.length; i++) {
750
Composite c = (Composite)items[i].getData("Panel");
751
Utils.disposeComposite(c);
752
items[i].setData("Panel", null);
754
items[i].setData("ConfigSectionSWT", null);
757
Utils.disposeComposite(cConfig);
759
Utils.disposeSWTObjects(new Object[] { headerFont, filterFoundFont });
761
filterFoundFont = null;
764
public String getFullTitle() {
765
return MessageText.getString("ConfigView.title.full"); //$NON-NLS-1$
768
public boolean selectSection(String id) {
769
TreeItem ti = findTreeItem(id);
772
tree.setSelection(new TreeItem[] { ti });
779
Class config_section_class )
781
TreeItem[] items = tree.getItems();
783
for (int i=0;i<items.length;i++){
785
TreeItem item = items[i];
787
ConfigSection section = (ConfigSection)item.getData("ConfigSectionSWT");
789
if ( section != null && section.getClass() == config_section_class ){
791
tree.setSelection( new TreeItem[]{ item });
2
* Created on 2 juil. 2003
3
* Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
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.
17
* AELITIS, SAS au capital de 46,603.30 euros
18
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
21
package org.gudy.azureus2.ui.swt.views;
23
import java.util.ArrayList;
24
import java.util.Arrays;
25
import java.util.Comparator;
27
import org.eclipse.swt.SWT;
28
import org.eclipse.swt.custom.SashForm;
29
import org.eclipse.swt.custom.ScrolledComposite;
30
import org.eclipse.swt.custom.StackLayout;
31
import org.eclipse.swt.events.*;
32
import org.eclipse.swt.graphics.*;
33
import org.eclipse.swt.layout.*;
34
import org.eclipse.swt.widgets.*;
36
import org.gudy.azureus2.core3.config.COConfigurationManager;
37
import org.gudy.azureus2.core3.internat.MessageText;
38
import org.gudy.azureus2.core3.logging.LogEvent;
39
import org.gudy.azureus2.core3.logging.LogIDs;
40
import org.gudy.azureus2.core3.logging.Logger;
41
import org.gudy.azureus2.core3.util.*;
42
import org.gudy.azureus2.pluginsimpl.local.ui.config.ConfigSectionRepository;
43
import org.gudy.azureus2.ui.swt.ImageRepository;
44
import org.gudy.azureus2.ui.swt.Messages;
45
import org.gudy.azureus2.ui.swt.Utils;
46
import org.gudy.azureus2.ui.swt.plugins.UISWTConfigSection;
47
import org.gudy.azureus2.ui.swt.views.configsections.*;
49
import com.aelitis.azureus.core.AzureusCore;
51
import org.gudy.azureus2.plugins.ui.config.ConfigSection;
52
import org.gudy.azureus2.plugins.ui.config.ConfigSectionSWT;
58
public class ConfigView extends AbstractIView {
59
private static final LogIDs LOGID = LogIDs.GUI;
60
public static final String sSectionPrefix = "ConfigView.section.";
62
AzureusCore azureus_core;
65
Composite cConfigSection;
66
StackLayout layoutConfigSection;
71
ArrayList pluginSections;
73
private Timer filterDelayTimer;
74
private String filterText = "";
76
private Listener scResizeListener;
81
* @param _azureus_core
85
AzureusCore _azureus_core )
87
azureus_core = _azureus_core;
91
* @see org.gudy.azureus2.ui.swt.IView#initialize(org.eclipse.swt.widgets.Composite)
93
public void initialize(Composite composite) {
96
/--cConfig-----------------------------------------------------------\
97
| ###SashForm#form################################################## |
98
| # /--cLeftSide-\ /--cRightSide---------------------------------\ # |
99
| # |txtFilter X | | ***cHeader********************************* | # |
100
| # | ##tree#### | | * lHeader * | # |
101
| # | # # | | ******************************************* | # |
102
| # | # # | | ###Composite cConfigSection################ | # |
103
| # | # # | | # # | # |
104
| # | # # | | # # | # |
105
| # | # # | | # # | # |
106
| # | # # | | # # | # |
107
| # | ########## | | ########################################### | # |
108
| # \------------/ \---------------------------------------------/ # |
109
| ################################################################## |
111
\--------------------------------------------------------------------/
114
Display d = composite.getDisplay();
116
cConfig = new Composite(composite, SWT.NONE);
117
GridLayout configLayout = new GridLayout();
118
configLayout.marginHeight = 0;
119
configLayout.marginWidth = 0;
120
cConfig.setLayout(configLayout);
121
gridData = new GridData(GridData.FILL_BOTH);
122
cConfig.setLayoutData(gridData);
124
SashForm form = new SashForm(cConfig,SWT.HORIZONTAL);
125
gridData = new GridData(GridData.FILL_BOTH);
126
form.setLayoutData(gridData);
128
Composite cLeftSide = new Composite(form, SWT.BORDER);
129
gridData = new GridData(GridData.FILL_BOTH);
130
cLeftSide.setLayoutData(gridData);
132
FormLayout layout = new FormLayout();
133
cLeftSide.setLayout(layout);
135
Composite cFilterArea = new Composite(cLeftSide, SWT.NONE);
136
cFilterArea.setLayout(new FormLayout());
138
final Text txtFilter = new Text(cFilterArea, SWT.BORDER);
139
final String sFilterText = MessageText.getString("ConfigView.filter");
140
txtFilter.setText(sFilterText);
141
txtFilter.selectAll();
142
txtFilter.addModifyListener(new ModifyListener() {
143
public void modifyText(ModifyEvent e) {
144
filterTree(txtFilter.getText());
147
txtFilter.addMouseListener(new MouseAdapter() {
148
public void mouseDown(MouseEvent e) {
149
if (txtFilter.getText().equals(sFilterText)) {
150
txtFilter.selectAll();
154
txtFilter.setFocus();
156
lblX = new Label(cFilterArea, SWT.WRAP);
157
Messages.setLanguageTooltip(lblX, "MyTorrentsView.clearFilter.tooltip");
158
lblX.setImage(ImageRepository.getImage("smallx-gray"));
159
lblX.addMouseListener(new MouseAdapter() {
160
public void mouseUp(MouseEvent e) {
161
txtFilter.setText("");
165
Label lblSearch = new Label(cFilterArea, SWT.NONE);
166
lblSearch.setImage(ImageRepository.getImage("search"));
168
tree = new Tree(cLeftSide, SWT.NONE);
169
FontData[] fontData = tree.getFont().getFontData();
170
fontData[0].setStyle(SWT.BOLD);
171
filterFoundFont = new Font(d, fontData);
175
formData = new FormData();
176
formData.bottom = new FormAttachment(100, -5);
177
formData.left = new FormAttachment(0, 0);
178
formData.right = new FormAttachment(100, 0);
179
cFilterArea.setLayoutData(formData);
181
formData = new FormData();
182
formData.top = new FormAttachment(0,5);
183
formData.left = new FormAttachment(0, 5);
184
lblSearch.setLayoutData(formData);
186
formData = new FormData();
187
formData.top = new FormAttachment(0,5);
188
formData.left = new FormAttachment(lblSearch,5);
189
formData.right = new FormAttachment(lblX, -3);
190
txtFilter.setLayoutData(formData);
192
formData = new FormData();
193
formData.top = new FormAttachment(0,5);
194
formData.right = new FormAttachment(100,-5);
195
lblX.setLayoutData(formData);
197
formData = new FormData();
198
formData.top = new FormAttachment(0, 0);
199
formData.left = new FormAttachment(0,0);
200
formData.right = new FormAttachment(100,0);
201
formData.bottom = new FormAttachment(cFilterArea,-1);
202
tree.setLayoutData(formData);
204
Composite cRightSide = new Composite(form, SWT.NULL);
205
configLayout = new GridLayout();
206
configLayout.marginHeight = 3;
207
configLayout.marginWidth = 0;
208
cRightSide.setLayout(configLayout);
211
Composite cHeader = new Composite(cRightSide, SWT.BORDER);
212
configLayout = new GridLayout();
213
configLayout.marginHeight = 3;
214
configLayout.marginWidth = 0;
215
cHeader.setLayout(configLayout);
216
gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER);
217
cHeader.setLayoutData(gridData);
219
cHeader.setBackground(d.getSystemColor(SWT.COLOR_LIST_SELECTION));
220
cHeader.setForeground(d.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT));
222
lHeader = new Label(cHeader, SWT.NULL);
223
lHeader.setBackground(d.getSystemColor(SWT.COLOR_LIST_SELECTION));
224
lHeader.setForeground(d.getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT));
225
fontData = lHeader.getFont().getFontData();
226
fontData[0].setStyle(SWT.BOLD);
227
int fontHeight = (int)(fontData[0].getHeight() * 1.2);
228
fontData[0].setHeight(fontHeight);
229
headerFont = new Font(d, fontData);
230
lHeader.setFont(headerFont);
231
gridData = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_CENTER);
232
lHeader.setLayoutData(gridData);
235
cConfigSection = new Composite(cRightSide, SWT.NULL);
236
layoutConfigSection = new StackLayout();
237
cConfigSection.setLayout(layoutConfigSection);
238
gridData = new GridData(GridData.FILL_BOTH);
239
gridData.horizontalIndent = 2;
240
cConfigSection.setLayoutData(gridData);
243
form.setWeights(new int[] {20,80});
245
tree.addSelectionListener(new SelectionAdapter() {
246
public void widgetSelected(SelectionEvent e) {
247
Tree tree = (Tree)e.getSource();
248
//Check that at least an item is selected
249
//OSX lets you select nothing in the tree for example when a child is selected
250
//and you close its parent.
251
if(tree.getSelection().length > 0)
252
showSection(tree.getSelection()[0]);
255
// Double click = expand/contract branch
256
tree.addListener(SWT.DefaultSelection, new Listener() {
257
public void handleEvent(Event e) {
258
TreeItem item = (TreeItem)e.item;
260
item.setExpanded(!item.getExpanded());
263
} catch (Exception e) {
264
Logger.log(new LogEvent(LOGID, "Error initializing ConfigView", e));
267
scResizeListener = new Listener() {
268
public void handleEvent(Event event) {
269
ScrolledComposite sc = (ScrolledComposite)event.widget;
271
Composite c = (Composite)sc.getContent();
273
Point size1 = c.computeSize(sc.getClientArea().width,
275
Point size = c.computeSize(SWT.DEFAULT, size1.y);
278
sc.getVerticalBar().setPageIncrement(sc.getSize().y);
284
/** How to add a new section
285
* 1) Create a new implementation of ConfigSectionSWT in a new file
286
* (Use the ConfigSectionTMP.java as a template if it's still around)
287
* 2) import it into here
288
* 3) add it to the internal sections list
290
pluginSections = ConfigSectionRepository.getInstance().getList();
292
ConfigSection[] internalSections = { new ConfigSectionConnection(),
293
new ConfigSectionConnectionProxy(),
294
new ConfigSectionConnectionAdvanced(),
295
new ConfigSectionConnectionEncryption(),
296
new ConfigSectionTransfer(azureus_core),
297
new ConfigSectionTransferAutoSpeedSelect(),
298
new ConfigSectionTransferAutoSpeed(),
299
new ConfigSectionTransferAutoSpeedBeta(),
300
new ConfigSectionTransferLAN(),
301
new ConfigSectionFile(),
302
new ConfigSectionFileMove(),
303
new ConfigSectionFileTorrents(),
304
new ConfigSectionFileTorrentsDecoding(),
305
new ConfigSectionFilePerformance(),
306
new ConfigSectionInterface(),
307
new ConfigSectionInterfaceLanguage(),
308
new ConfigSectionInterfaceStart(),
309
new ConfigSectionInterfaceDisplay(),
310
new ConfigSectionInterfaceColor(),
311
new ConfigSectionInterfaceAlerts(),
312
new ConfigSectionMode(),
313
new ConfigSectionIPFilter(azureus_core),
314
new ConfigSectionPlugins(this, azureus_core),
315
new ConfigSectionStats(),
316
new ConfigSectionTracker(azureus_core),
317
new ConfigSectionTrackerClient(),
318
new ConfigSectionTrackerServer(azureus_core),
319
new ConfigSectionSecurity(),
320
new ConfigSectionSharing(),
321
new ConfigSectionLogging()
324
pluginSections.addAll(0, Arrays.asList(internalSections));
326
for (int i = 0; i < pluginSections.size(); i++) {
328
// slip the non-standard "plugins" initialisation inbetween the internal ones
329
// and the plugin ones so plugin ones can be children of it
331
boolean plugin_section = i >= internalSections.length;
333
ConfigSection section = (ConfigSection)pluginSections.get(i);
335
if (section instanceof ConfigSectionSWT || section instanceof UISWTConfigSection ) {
338
name = section.configSectionGetName();
339
} catch (Exception e) {
340
Logger.log(new LogEvent(LOGID, "A ConfigSection plugin caused an "
341
+ "error while trying to call its "
342
+ "configSectionGetName function", e));
346
String section_key = name;
348
if ( plugin_section ){
349
// if resource exists without prefix then use it as plugins don't
350
// need to start with the prefix
352
if ( !MessageText.keyExists(section_key)){
354
section_key = sSectionPrefix + name;
359
section_key = sSectionPrefix + name;
364
String location = section.configSectionGetParentSection();
366
if (location.equalsIgnoreCase(ConfigSection.SECTION_ROOT))
367
treeItem = new TreeItem(tree, SWT.NULL);
368
else if (location != "") {
369
TreeItem treeItemFound = findTreeItem(tree, location);
370
if (treeItemFound != null){
371
if (location.equalsIgnoreCase(ConfigSection.SECTION_PLUGINS)) {
372
// Force ordering by name here.
373
int position = findInsertPointFor(MessageText.getString(section_key), treeItemFound);
374
if (position == -1) {
375
treeItem = new TreeItem(treeItemFound, SWT.NULL);
378
treeItem = new TreeItem(treeItemFound, SWT.NULL, position);
382
treeItem = new TreeItem(treeItemFound, SWT.NULL);
385
treeItem = new TreeItem(tree, SWT.NULL);
388
treeItem = new TreeItem(tree, SWT.NULL);
391
ScrolledComposite sc = new ScrolledComposite(cConfigSection, SWT.H_SCROLL | SWT.V_SCROLL);
392
sc.setExpandHorizontal(true);
393
sc.setExpandVertical(true);
394
sc.setLayoutData(new GridData(GridData.FILL_BOTH));
395
sc.getVerticalBar().setIncrement(16);
396
sc.addListener(SWT.Resize, scResizeListener);
400
if ( section instanceof ConfigSectionSWT ){
402
c = ((ConfigSectionSWT)section).configSectionCreate(sc);
406
c = ((UISWTConfigSection)section).configSectionCreate(sc);
411
Messages.setLanguageText(treeItem, section_key);
412
treeItem.setData("Panel", sc);
413
treeItem.setData("ID", name);
414
treeItem.setData("ConfigSectionSWT", section);
416
// ConfigSectionPlugins is special because it has to handle the
417
// PluginConfigModel config pages
418
if (section instanceof ConfigSectionPlugins)
419
((ConfigSectionPlugins)section).initPluginSubSections();
420
} catch (Exception e) {
421
Logger.log(new LogEvent(LOGID, "ConfigSection plugin '" + name
422
+ "' caused an error", e));
432
TreeItem[] items = { tree.getItems()[0] };
433
tree.setSelection(items);
434
// setSelection doesn't trigger a SelectionListener, so..
435
showSection(items[0]);
441
protected void filterTree(String text) {
443
if (filterDelayTimer != null) {
444
filterDelayTimer.destroy();
447
if (lblX != null && !lblX.isDisposed()) {
448
Image img = ImageRepository.getImage(filterText.length() > 0 ? "smallx"
455
filterDelayTimer = new Timer("Filter");
456
filterDelayTimer.addEvent(SystemTime.getCurrentTime() + 300,
457
new TimerEventPerformer() {
458
public void perform(TimerEvent event) {
459
filterDelayTimer.destroy();
460
filterDelayTimer = null;
462
Utils.execSWTThread(new AERunnable() {
463
public void runSupport() {
464
// TODO Auto-generated method stub
465
ArrayList foundItems = new ArrayList();
466
TreeItem[] items = tree.getItems();
468
tree.setRedraw(false);
469
for (int i = 0; i < items.length; i++) {
470
items[i].setExpanded(false);
473
filterTree(items, filterText, foundItems);
475
tree.setRedraw(true);
483
protected void filterTree(TreeItem[] items, String text, ArrayList foundItems)
485
text = text.toLowerCase();
486
for (int i = 0; i < items.length; i++) {
487
ensureSectionBuilt(items[i]);
488
ScrolledComposite composite = (ScrolledComposite) items[i].getData("Panel");
490
if (text.length() > 0
491
&& (items[i].getText().toLowerCase().indexOf(text) >= 0 || compositeHasText(
493
foundItems.add(items[i]);
495
ensureExpandedTo(items[i]);
496
items[i].setFont(filterFoundFont);
498
items[i].setFont(null);
500
filterTree(items[i].getItems(), text, foundItems);
504
private void ensureExpandedTo(TreeItem item) {
505
TreeItem itemParent = item.getParentItem();
506
if (itemParent != null) {
507
itemParent.setExpanded(true);
508
ensureExpandedTo(itemParent);
517
private boolean compositeHasText(Composite composite, String text) {
518
Control[] children = composite.getChildren();
520
for (int i = 0; i < children.length; i++) {
521
Control child = children[i];
522
if (child instanceof Label) {
523
if (((Label)child).getText().toLowerCase().indexOf(text) >= 0) {
526
} else if (child instanceof Group) {
527
if (((Group)child).getText().toLowerCase().indexOf(text) >= 0) {
530
} else if (child instanceof Button) {
531
if (((Button)child).getText().toLowerCase().indexOf(text) >= 0) {
536
if (child instanceof Composite) {
537
if (compositeHasText((Composite) child, text)) {
546
private void showSection(TreeItem section) {
547
ScrolledComposite item = (ScrolledComposite)section.getData("Panel");
551
ensureSectionBuilt(section);
553
layoutConfigSection.topControl = item;
555
// Composite c = (Composite)item.getContent();
558
// resize listener will sc.setMinSize
559
// System.out.println("show");
560
// item.setMinSize(c.computeSize(SWT.DEFAULT, SWT.DEFAULT));
561
cConfigSection.layout();
563
updateHeader(section);
567
private void ensureSectionBuilt(TreeItem section) {
568
ScrolledComposite item = (ScrolledComposite)section.getData("Panel");
572
ConfigSection configSection = (ConfigSection)section.getData("ConfigSectionSWT");
574
if (configSection != null) {
576
Control previous = item.getContent();
577
if (previous instanceof Composite) {
578
configSection.configSectionDelete();
579
Utils.disposeComposite((Composite)previous,true);
584
if ( configSection instanceof ConfigSectionSWT ){
586
c = ((ConfigSectionSWT)configSection).configSectionCreate(item);
590
c = ((UISWTConfigSection)configSection).configSectionCreate(item);
598
private void updateHeader(TreeItem section) {
602
String sHeader = section.getText();
603
section = section.getParentItem();
604
while (section != null) {
605
sHeader = section.getText() + " : " + sHeader;
606
section = section.getParentItem();
608
lHeader.setText(" " + sHeader.replaceAll("&", "&&"));
612
private Composite createConfigSection(String sNameID) {
613
return createConfigSection(null, sNameID, -1, true);
616
private Composite createConfigSection(String sNameID, int position) {
617
return createConfigSection(null, sNameID, position, true);
620
public Composite createConfigSection(TreeItem treeItemParent,
624
ScrolledComposite sc = new ScrolledComposite(cConfigSection, SWT.H_SCROLL | SWT.V_SCROLL);
625
sc.setExpandHorizontal(true);
626
sc.setExpandVertical(true);
627
sc.setLayoutData(new GridData(GridData.FILL_BOTH));
628
sc.getVerticalBar().setIncrement(16);
629
sc.addListener(SWT.Resize, scResizeListener);
631
Composite cConfigSection = new Composite(sc, SWT.NULL);
633
String section_key = ((bPrefix) ? sSectionPrefix : "") + sNameID;
635
if (position == -2) { // Means "auto-order".
636
position = findInsertPointFor(MessageText.getString(section_key), (treeItemParent == null) ? (Object)tree : (Object)treeItemParent);
640
if (treeItemParent == null) {
642
treeItem = new TreeItem(tree, SWT.NULL, position);
644
treeItem = new TreeItem(tree, SWT.NULL);
647
treeItem = new TreeItem(treeItemParent, SWT.NULL, position);
649
treeItem = new TreeItem(treeItemParent, SWT.NULL);
651
Messages.setLanguageText(treeItem, section_key);
652
treeItem.setData("Panel", sc);
653
treeItem.setData("ID", sNameID);
655
sc.setContent(cConfigSection);
656
return cConfigSection;
659
private static Comparator insert_point_comparator = new Comparator() {
661
private String asString(Object o) {
662
if (o instanceof String) {
665
else if (o instanceof TreeItem) {
666
return ((TreeItem)o).getText();
669
throw new ClassCastException("object is not String or TreeItem: " + o.getClass().getName());
673
public int compare(Object o1, Object o2) {
674
int result = String.CASE_INSENSITIVE_ORDER.compare(asString(o1), asString(o2));
679
public static int findInsertPointFor(String name, Object structure) {
680
TreeItem[] children = null;
681
if (structure instanceof Tree) {
682
children = ((Tree)structure).getItems();
685
children = ((TreeItem)structure).getItems();
687
if (children.length == 0) {return -1;}
688
int result = Arrays.binarySearch(children, name, insert_point_comparator);
689
if (result > 0) {return result;}
690
result = -(result+1);
691
if (result == children.length) {
697
public TreeItem findTreeItem(String ID) {
698
return findTreeItem((Tree)null, ID);
701
private TreeItem findTreeItem(Tree tree, String ID) {
704
TreeItem[] items = tree.getItems();
705
for (int i = 0; i < items.length; i++) {
706
String itemID = (String)items[i].getData("ID");
707
if (itemID != null && itemID.equalsIgnoreCase(ID)) {
710
TreeItem itemFound = findTreeItem(items[i], ID);
711
if (itemFound != null)
717
private TreeItem findTreeItem(TreeItem item, String ID) {
718
TreeItem[] subItems = item.getItems();
719
for (int i = 0; i < subItems.length; i++) {
720
String itemID = (String)subItems[i].getData("ID");
721
if (itemID != null && itemID.equalsIgnoreCase(ID)) {
725
TreeItem itemFound = findTreeItem(subItems[i], ID);
726
if (itemFound != null)
732
private void initSaveButton() {
734
final Button save = new Button(cConfig, SWT.PUSH);
735
Messages.setLanguageText(save, "ConfigView.button.save"); //$NON-NLS-1$
736
gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
737
gridData.horizontalSpan = 2;
738
gridData.widthHint = 80;
739
save.setLayoutData(gridData);
741
save.addSelectionListener(new SelectionAdapter() {
742
public void widgetSelected(SelectionEvent event) {
743
// force focusout on osx
745
COConfigurationManager.setParameter("updated", 1);
746
COConfigurationManager.save();
748
for (int i = 0; i < pluginSections.size(); i++)
749
((ConfigSection) pluginSections.get(i)).configSectionSave();
755
* @see org.gudy.azureus2.ui.swt.IView#getComposite()
757
public Composite getComposite() {
761
public void updateLanguage() {
762
super.updateLanguage();
763
updateHeader(tree.getSelection()[0]);
764
// cConfig.setSize(cConfig.computeSize(SWT.DEFAULT, SWT.DEFAULT));
767
public void delete() {
768
for (int i = 0; i < pluginSections.size(); i++) {
770
((ConfigSection)pluginSections.get(i)).configSectionDelete();
771
} catch (Exception e) {
772
Debug.out("Error while deleting config section", e);
775
pluginSections.clear();
776
if(! tree.isDisposed()) {
777
TreeItem[] items = tree.getItems();
778
for (int i = 0; i < items.length; i++) {
779
Composite c = (Composite)items[i].getData("Panel");
780
Utils.disposeComposite(c);
781
items[i].setData("Panel", null);
783
items[i].setData("ConfigSectionSWT", null);
786
Utils.disposeComposite(cConfig);
788
Utils.disposeSWTObjects(new Object[] { headerFont, filterFoundFont });
790
filterFoundFont = null;
793
public String getFullTitle() {
794
return MessageText.getString("ConfigView.title.full"); //$NON-NLS-1$
797
public boolean selectSection(String id) {
798
TreeItem ti = findTreeItem(id);
801
tree.setSelection(new TreeItem[] { ti });
808
Class config_section_class )
810
TreeItem[] items = tree.getItems();
812
for (int i=0;i<items.length;i++){
814
TreeItem item = items[i];
816
ConfigSection section = (ConfigSection)item.getData("ConfigSectionSWT");
818
if ( section != null && section.getClass() == config_section_class ){
820
tree.setSelection( new TreeItem[]{ item });