1 /*
2  * File    : MultiTrackerEditor.java
3  * Created : 3 déc. 2003}
4  * By      : Olivier
5  *
6  * Azureus - a Java Bittorrent client
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details ( see the LICENSE file ).
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22 package org.gudy.azureus2.ui.swt.maketorrent;
23 
24 import org.eclipse.swt.SWT;
25 import org.eclipse.swt.custom.TreeEditor;
26 import org.eclipse.swt.events.*;
27 import org.eclipse.swt.graphics.Point;
28 import org.eclipse.swt.graphics.Rectangle;
29 import org.eclipse.swt.layout.GridData;
30 import org.eclipse.swt.layout.GridLayout;
31 import org.eclipse.swt.widgets.*;
32 import org.gudy.azureus2.ui.swt.Messages;
33 import org.gudy.azureus2.ui.swt.Utils;
34 import org.gudy.azureus2.ui.swt.mainwindow.Colors;
35 
36 import java.net.URL;
37 import java.util.Iterator;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.HashMap;
41 import java.util.ArrayList;
42 
43 
44 /**
45  * @author Olivier
46  *
47  */
48 public class WebSeedsEditor {
49 
50   WebSeedsEditorListener listener;
51   String oldName;
52   String currentName;
53   boolean	anonymous;
54 
55   Map webseeds;
56 
57   Display display;
58   Shell shell;
59   Text textName;
60   Tree treeGroups;
61   TreeEditor editor;
62   TreeItem itemEdited;
63   Button btnSave;
64   Button btnCancel;
65 
66   Menu menu;
67 
WebSeedsEditor(String name,Map webseeds,WebSeedsEditorListener listener)68   public WebSeedsEditor(String name,Map webseeds,WebSeedsEditorListener listener) {
69   	this( name, webseeds, listener, false );
70   }
71 
72   public
WebSeedsEditor( String name, Map webseeds, WebSeedsEditorListener listener, boolean _anonymous )73   WebSeedsEditor(
74   		String 					name,
75 		Map 					webseeds,
76 		WebSeedsEditorListener 	listener,
77 		boolean					_anonymous )
78   {
79   		this.oldName = name;
80     if(name != null)
81       this.currentName = name;
82     else
83       this.currentName = "";
84     this.listener = listener;
85     anonymous = _anonymous;
86     this.webseeds = new HashMap(webseeds);
87     createWindow();
88 
89   }
90 
createWindow()91   private void createWindow() {
92     this.display = Display.getCurrent();
93     this.shell = org.gudy.azureus2.ui.swt.components.shell.ShellFactory.createShell(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
94     Messages.setLanguageText(this.shell,"wizard.webseedseditor.edit.title");
95     Utils.setShellIcon(shell);
96     GridLayout layout = new GridLayout();
97     layout.numColumns = 3;
98     shell.setLayout(layout);
99 
100     GridData gridData;
101 
102     if ( !anonymous ){
103 
104 	    Label labelName = new Label(shell,SWT.NULL);
105 	    Messages.setLanguageText(labelName,"wizard.multitracker.edit.name");
106 
107 	    textName = new Text(shell,SWT.BORDER);
108 	    textName.setText(currentName);
109 	    gridData = new GridData(GridData.FILL_HORIZONTAL);
110 	    gridData.horizontalSpan = 2;
111 	    Utils.setLayoutData(textName, gridData);
112 	    textName.addModifyListener(new ModifyListener() {
113 		    public void modifyText(ModifyEvent arg0) {
114 		      currentName = textName.getText();
115 		      computeSaveEnable();
116 		    }
117 	    });
118     }
119 
120     treeGroups = new Tree(shell,SWT.BORDER);
121     gridData = new GridData(GridData.FILL_BOTH);
122     gridData.horizontalSpan = 3;
123     gridData.heightHint = 150;
124     Utils.setLayoutData(treeGroups, gridData);
125 
126     treeGroups.addMouseListener(
127     		new MouseAdapter()
128     		{
129     			public void
130     			mouseDoubleClick(
131     				MouseEvent arg0 )
132     			{
133     				if(treeGroups.getSelectionCount() == 1) {
134     					TreeItem treeItem = treeGroups.getSelection()[0];
135     					String type = (String) treeItem.getData("type");
136     					if(type.equals("tracker")) {
137     						editTreeItem(treeItem);
138     					}
139     				}
140     			}
141     		});
142 
143     Label labelSeparator = new Label(shell,SWT.SEPARATOR | SWT.HORIZONTAL);
144     gridData = new GridData(GridData.FILL_HORIZONTAL);
145     gridData.horizontalSpan = 3;
146     Utils.setLayoutData(labelSeparator, gridData);
147 
148     	// button row
149 
150     Label label = new Label(shell,SWT.NULL);
151     gridData = new GridData(GridData.FILL_HORIZONTAL );
152     Utils.setLayoutData(label, gridData);
153 
154     Composite cButtons = new Composite(shell, SWT.NULL);
155     gridData = new GridData(GridData.FILL_HORIZONTAL);
156     gridData.horizontalSpan = 3;
157     Utils.setLayoutData(cButtons, gridData);
158     GridLayout layoutButtons = new GridLayout();
159     layoutButtons.numColumns = 3;
160     cButtons.setLayout(layoutButtons);
161     label = new Label(cButtons,SWT.NULL);
162     gridData = new GridData(GridData.FILL_HORIZONTAL );
163     Utils.setLayoutData(label, gridData);
164 
165     btnSave = new Button(cButtons,SWT.PUSH);
166     gridData = new GridData();
167     gridData.widthHint = 70;
168     gridData.horizontalAlignment = GridData.END;
169     Utils.setLayoutData(btnSave, gridData);
170     Messages.setLanguageText(btnSave,"wizard.multitracker.edit.save");
171     btnSave.addListener(SWT.Selection, new Listener() {
172       public void handleEvent(Event e) {
173         update();
174         shell.dispose();
175       }
176     });
177 
178     btnCancel = new Button(cButtons,SWT.PUSH);
179     gridData = new GridData();
180     gridData.horizontalAlignment = GridData.END;
181     gridData.widthHint = 70;
182     Utils.setLayoutData(btnCancel, gridData);
183     Messages.setLanguageText(btnCancel,"Button.cancel");
184     btnCancel.addListener(SWT.Selection, new Listener() {
185       public void handleEvent(Event e) {
186         shell.dispose();
187       }
188     });
189 
190     shell.setDefaultButton( btnSave );
191 
192     shell.addListener(SWT.Traverse, new Listener() {
193     	public void handleEvent(Event e) {
194     		if ( e.character == SWT.ESC){
195     			shell.dispose();
196     		}
197     	}
198     });
199 
200 
201     computeSaveEnable();
202     refresh();
203     constructMenu();
204 
205     editor = new TreeEditor (treeGroups);
206     treeGroups.addSelectionListener(new SelectionAdapter() {
207 	    public void widgetSelected(SelectionEvent arg0) {
208 	      if(itemEdited != null && !editor.getEditor().isDisposed())
209 	        itemEdited.setText(((Text)editor.getEditor()).getText());
210 	      removeEditor();
211 	    }
212     });
213 
214     shell.pack();
215 
216     Point size = shell.computeSize(400,SWT.DEFAULT);
217     shell.setSize(size);
218 
219     Utils.centreWindow( shell );
220 
221     shell.open();
222   }
223 
update()224   private void update() {
225     webseeds = new HashMap();
226     TreeItem[] groupItems = treeGroups.getItems();
227 
228     for(int i = 0 ; i < groupItems.length ; i++) {
229       TreeItem group = groupItems[i];
230       TreeItem[] trackerItems = group.getItems();
231       List groupList = new ArrayList(group.getItemCount());
232       for(int j = 0 ; j < trackerItems.length ; j++) {
233         groupList.add(trackerItems[j].getText());
234       }
235       webseeds.put(group.getText(),groupList);
236     }
237 
238     listener.webSeedsChanged(oldName,currentName,webseeds);
239     oldName = currentName;
240   }
241 
computeSaveEnable()242   private void computeSaveEnable()
243   {
244   	boolean	enabled = anonymous || !("".equals(currentName));
245 
246   	if ( enabled ){
247 
248  	  	TreeItem[] groupItems = treeGroups.getItems();
249 
250  	  	outer:
251 	  	for(int i = 0 ; i < groupItems.length ; i++) {
252 	  		TreeItem group = groupItems[i];
253 	  		TreeItem[] trackerItems = group.getItems();
254 	  		for(int j = 0 ; j < trackerItems.length ; j++) {
255 
256 	  			if ( ! validURL(trackerItems[j].getText())){
257 
258 	  				enabled = false;
259 
260 	  				break outer;
261 		  		}
262 		  	}
263 	  	}
264   	}
265 
266   	if ( enabled != btnSave.getEnabled()){
267 
268   		btnSave.setEnabled( enabled );
269   	}
270   }
271 
refresh()272   private void refresh() {
273     treeGroups.removeAll();
274     Iterator iter = webseeds.entrySet().iterator();
275     while(iter.hasNext()) {
276       Map.Entry entry = (Map.Entry) iter.next();
277       TreeItem itemRoot = newGroup((String)entry.getKey());
278       Iterator iter2 = ((List)entry.getValue()).iterator();
279       while(iter2.hasNext()) {
280         String url =  (String) iter2.next();
281         newTracker(itemRoot,url);
282       }
283     }
284   }
285 
constructMenu()286   private void constructMenu() {
287     menu = new Menu(shell,SWT.NULL);
288     menu.addListener(SWT.Show, new Listener() {
289       public void handleEvent(Event e) {
290         //1. Empty the menu
291         MenuItem[] items = menu.getItems();
292         for(int i = 0 ; i < items.length ; i++) {
293           items[i].dispose();
294         }
295 
296 
297         //3. Grab the element
298         final TreeItem treeItem = treeGroups.getSelection()[0];
299         String type = (String) treeItem.getData("type");
300         if(type.equals("tracker")) {
301           //The Tracker menu
302           MenuItem item = new MenuItem(menu,SWT.NULL);
303           Messages.setLanguageText(item,"wizard.multitracker.edit.deletetracker");
304           item.addListener(SWT.Selection,new Listener(){
305             public void handleEvent(Event arg0) {
306               treeItem.dispose();
307             }
308           });
309 
310           item = new MenuItem(menu,SWT.NULL);
311           Messages.setLanguageText(item,"wizard.multitracker.edit.edit");
312           item.addListener(SWT.Selection,new Listener(){
313 	          public void handleEvent(Event arg0) {
314 	            editTreeItem(treeItem);
315 	          }
316           });
317         } else
318         if(type.equals("group")) {
319           //The Group menu
320 
321           MenuItem item = new MenuItem(menu,SWT.NULL);
322           Messages.setLanguageText(item,"wizard.webseedseditor.edit.newseed");
323           item.addListener(SWT.Selection, new Listener() {
324             public void handleEvent(Event arg0) {
325               TreeItem itemTracker = newTracker(treeItem,"http://");
326               editTreeItem(itemTracker);
327             }
328           });
329         }
330       }
331     });
332     treeGroups.setMenu(menu);
333   }
334 
editTreeItem(final TreeItem item)335   private void editTreeItem(final TreeItem item) {
336     // Clean up any previous editor control
337     Control oldEditor = editor.getEditor();
338     if (oldEditor != null)
339       oldEditor.dispose();
340 
341     itemEdited = item;
342     // The control that will be the editor must be a child of the Tree
343     final Text text = new Text(treeGroups, SWT.BORDER);
344     text.setText(item.getText());
345     text.setForeground(item.getForeground());
346     text.setSelection(item.getText().length());
347     text.addListener (SWT.DefaultSelection, new Listener () {
348       public void handleEvent (Event e) {
349       	String url = text.getText();
350       	if ( validURL(url)){
351       		text.setForeground( null );
352       		item.setForeground( null );
353       	}else{
354       		text.setForeground( Colors.colorError );
355       		item.setForeground( Colors.colorError );
356       	}
357       	item.setText(url);
358         computeSaveEnable();
359         removeEditor();
360       }
361     });
362 
363     text.addListener(SWT.Modify, new Listener() {
364     	public void handleEvent (Event e) {
365     		String url = text.getText();
366     		if ( validURL(url)){
367     			text.setForeground( null );
368     			item.setForeground( null );
369     		}else{
370     			text.setForeground( Colors.colorError );
371     			item.setForeground( Colors.colorError );
372     		}
373     		item.setText(url);
374      		computeSaveEnable();
375     	}
376     });
377 
378     text.addKeyListener(new KeyAdapter() {
379 	    public void keyReleased(KeyEvent keyEvent) {
380 	     if(keyEvent.character == SWT.ESC) {
381 	       removeEditor();
382 	     }
383 	    }
384     });
385 
386 
387     //The text editor must have the same size as the cell and must
388     //not be any smaller than 50 pixels.
389     editor.horizontalAlignment = SWT.LEFT;
390     editor.grabHorizontal = true;
391     editor.minimumWidth = 50;
392 
393     Rectangle r = text.computeTrim(0, 0, 100, text.getLineHeight());
394     editor.minimumHeight = r.height;
395 
396 
397     // Open the text editor on the selected row.
398     editor.setEditor (text, item);
399 
400     // Assign focus to the text control
401     text.setFocus ();
402   }
403 
404   private boolean
validURL( String str )405   validURL(
406   	String	str )
407   {
408   	try{
409   		URL url = new URL(str);
410 
411   		String prot = url.getProtocol().toLowerCase();
412 
413   		if ( prot.startsWith( "http" )){
414 
415   			return( true );
416   		}
417 
418   		return( false );
419 
420   	}catch( Throwable e ){
421 
422   		return( false );
423   	}
424   }
425 
removeEditor()426   private void removeEditor() {
427     Control oldEditor = editor.getEditor();
428     if (oldEditor != null)
429       oldEditor.dispose();
430   }
431 
newGroup(String name)432   private TreeItem newGroup(String name) {
433     TreeItem item = new TreeItem(treeGroups,SWT.NULL);
434     item.setData("type","group");
435     item.setText(name);
436     return item;
437   }
438 
newTracker(TreeItem root,String url)439   private TreeItem newTracker(TreeItem root,String url) {
440     TreeItem item = new TreeItem(root,SWT.NULL);
441     item.setText(url);
442     item.setData("type","tracker");
443     root.setExpanded(true);
444     return item;
445   }
446 }
447