/** * Created on Jun 23, 2008 * * Copyright 2008 Vuze, Inc. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.aelitis.azureus.ui.swt.views.skin.sidebar; import java.util.ArrayList; import java.util.List; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.*; import org.eclipse.swt.events.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.widgets.*; import org.gudy.azureus2.core3.config.COConfigurationManager; import org.gudy.azureus2.core3.config.impl.ConfigurationChecker; import org.gudy.azureus2.core3.util.*; import org.gudy.azureus2.plugins.PluginInterface; import org.gudy.azureus2.plugins.ui.menus.MenuItem; import org.gudy.azureus2.plugins.ui.menus.MenuItemListener; import org.gudy.azureus2.pluginsimpl.local.ui.config.ConfigSectionHolder; import org.gudy.azureus2.pluginsimpl.local.ui.config.ConfigSectionRepository; import org.gudy.azureus2.ui.common.util.MenuItemManager; import org.gudy.azureus2.ui.swt.MenuBuildUtils; import org.gudy.azureus2.ui.swt.URLTransfer; import org.gudy.azureus2.ui.swt.Utils; import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener; import org.gudy.azureus2.ui.swt.plugins.PluginUISWTSkinObject; import org.gudy.azureus2.ui.swt.plugins.UISWTView; import org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener; import org.gudy.azureus2.ui.swt.views.*; import com.aelitis.azureus.core.AzureusCore; import com.aelitis.azureus.core.AzureusCoreFactory; import com.aelitis.azureus.core.AzureusCoreRunningListener; import com.aelitis.azureus.core.cnetwork.ContentNetwork; import com.aelitis.azureus.core.cnetwork.ContentNetworkManager; import com.aelitis.azureus.core.cnetwork.ContentNetworkManagerFactory; import com.aelitis.azureus.ui.UIFunctions; import com.aelitis.azureus.ui.UIFunctionsManager; import com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo; import com.aelitis.azureus.ui.mdi.*; import com.aelitis.azureus.ui.swt.mdi.*; import com.aelitis.azureus.ui.swt.shells.AuthorizeWindow; import com.aelitis.azureus.ui.swt.skin.*; import com.aelitis.azureus.ui.swt.skin.SWTSkinButtonUtility.ButtonListenerAdapter; import com.aelitis.azureus.ui.swt.utils.ContentNetworkUI; import com.aelitis.azureus.ui.swt.utils.ContentNetworkUI.ContentNetworkImageLoadedListener; import com.aelitis.azureus.ui.swt.utils.FontUtils; import com.aelitis.azureus.util.ConstantsVuze; import com.aelitis.azureus.util.ContentNetworkUtils; /** * @author TuxPaper * @created Jun 23, 2008 * */ public class SideBar extends BaseMDI { private static final boolean END_INDENT = Constants.isLinux || Constants.isWindows2000 || Constants.isWindows9598ME; private static final boolean USE_PAINTITEM = Utils.isCocoa || Constants.isWindows; // Need to use paint even on Cocoa, because there's cases where an area // will become invalidated and we don't get a paintitem :( private static final boolean USE_PAINT = !Constants.isWindows; protected static final boolean HIDE_NATIVE_EXPANDER = false; private static final boolean GAP_BETWEEN_LEVEL_1 = true; private SWTSkin skin; private SWTSkinObjectContainer soSideBarContents; private SWTSkinObject soSideBarList; private Tree tree; private Font fontHeader; private Font font; private SWTSkinObject soSideBarPopout; private SelectionListener dropDownSelectionListener; private DropTarget dropTarget; protected SideBarEntrySWT draggingOver; private Color fg; private Color bg; private List<MdiSWTMenuHackListener> listMenuHackListners; public static SideBar instance = null; public SideBar() { super(); if (instance == null) { instance = this; } } // @see com.aelitis.azureus.ui.swt.skin.SWTSkinObjectAdapter#skinObjectCreated(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectCreated(SWTSkinObject skinObject, Object params) { super.skinObjectCreated(skinObject, params); skin = skinObject.getSkin(); soSideBarContents = (SWTSkinObjectContainer) skin.getSkinObject("sidebar-contents"); soSideBarList = skin.getSkinObject("sidebar-list"); soSideBarPopout = skin.getSkinObject("sidebar-pop"); if (ConfigurationChecker.isNewVersion() && Constants.compareVersions(Constants.AZUREUS_VERSION, "4.5.0.4") == 0) { final SWTSkinObjectSash soSash = (SWTSkinObjectSash) skin.getSkinObject("sidebar-sash"); if (soSash != null) { soSash.resetWidth(); } } // addTestMenus(); createSideBar(); try { UIFunctionsManager.getUIFunctions().getUIUpdater().addUpdater(this); } catch (Exception e) { Debug.out(e); } Display.getDefault().addFilter(SWT.KeyDown, new Listener() { public void handleEvent(Event event) { // F9 is standard Seamonkey, but doesn't work on OSX // Command Option T is standard on OSX // F7 works on both if (event.keyCode == SWT.F9 || event.keyCode == SWT.F7 || (event.keyCode == 116 && event.stateMask == (SWT.COMMAND | SWT.ALT))) { event.doit = false; event.keyCode = 0; event.character = '\0'; flipSideBarVisibility(); } } }); return null; } /** * * * @since 3.1.0.1 */ /* private void addTestMenus() { // Add some test menus PluginManager pm = AzureusCoreFactory.getSingleton().getPluginManager(); PluginInterface pi = pm.getDefaultPluginInterface(); UIManager uim = pi.getUIManager(); MenuManager menuManager = uim.getMenuManager(); MenuItem menuItem = menuManager.addMenuItem("sidebar", "test menu"); menuItem.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { ToolBarView tb = (ToolBarView) SkinViewManager.getByClass(ToolBarView.class); if (tb != null) { System.out.println("Found download Toolbar"); ToolBarItem dlItem = tb.getToolBarItem("download"); System.out.println("Download ToolBar Item is " + dlItem); if (dlItem != null) { System.out.println(dlItem.getSkinButton().getSkinObject()); } dlItem.setEnabled(!dlItem.isEnabled()); } if (target instanceof SideBarEntry) { SideBarEntry info = (SideBarEntry) target; System.err.println(info.getId() + " of " + info.getParentID() + ";ds=" + info.getDatasource()); } } }); menuItem = menuManager.addMenuItem("sidebar." + SIDEBAR_SECTION_ACTIVITIES, "Activity Only Menu"); menuItem.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { if (target instanceof SideBarEntry) { SideBarEntry info = (SideBarEntry) target; System.err.println(info.getId() + " of " + info.getParentID() + ";ds=" + info.getDatasource()); } } }); } */ /** * * * @since 3.1.1.1 */ public void flipSideBarVisibility() { final SWTSkinObjectSash soSash = (SWTSkinObjectSash) skin.getSkinObject("sidebar-sash"); if (soSash == null) { return; } Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { soSash.setAboveVisible(!soSash.isAboveVisible()); updateSidebarVisibility(); } }); } private void updateSidebarVisibility() { Utils.execSWTThread(new AERunnable() { public void runSupport() { final SWTSkinObjectSash soSash = (SWTSkinObjectSash) skin.getSkinObject("sidebar-sash"); if (soSash == null) { return; } if (soSash.isAboveVisible()) { if (soSideBarPopout != null) { Object ld = soSideBarPopout.getControl().getLayoutData(); if (ld instanceof FormData) { FormData fd = (FormData) ld; fd.width = 0; } soSideBarPopout.setVisible(false); Utils.relayout(soSideBarPopout.getControl()); } } else { if (soSideBarPopout != null) { Object ld = soSideBarPopout.getControl().getLayoutData(); if (ld instanceof FormData) { FormData fd = (FormData) ld; fd.width = 24; } soSideBarPopout.setVisible(true); soSideBarPopout.getControl().moveAbove(null); Utils.relayout(soSideBarPopout.getControl()); } } } }); } public boolean isVisible() { SWTSkinObjectSash soSash = (SWTSkinObjectSash) skin.getSkinObject("sidebar-sash"); if (soSash == null) { return false; } return soSash.isAboveVisible(); } // @see com.aelitis.azureus.ui.swt.views.skin.SkinView#showSupport(com.aelitis.azureus.ui.swt.skin.SWTSkinObject, java.lang.Object) public Object skinObjectInitialShow(SWTSkinObject skinObject, Object params) { // building plugin views needs UISWTInstance, which needs core. AzureusCoreFactory.addCoreRunningListener(new AzureusCoreRunningListener() { public void azureusCoreRunning(AzureusCore core) { Utils.execSWTThread(new AERunnable() { public void runSupport() { setupPluginViews(); } }); } }); try { loadCloseables(); } catch (Throwable t) { Debug.out(t); } updateSidebarVisibility(); return null; } public Object skinObjectDestroyed(SWTSkinObject skinObject, Object params) { try { UIFunctionsManager.getUIFunctions().getUIUpdater().removeUpdater(this); } catch (Exception e) { Debug.out(e); } return null; } private void createSideBar() { if (soSideBarList == null) { return; } Composite parent = (Composite) soSideBarList.getControl(); tree = new Tree(parent, SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.DOUBLE_BUFFERED | SWT.NO_SCROLL); tree.setHeaderVisible(false); new SideBarToolTips(this, tree); tree.setLayoutData(Utils.getFilledFormData()); SWTSkinProperties skinProperties = skin.getSkinProperties(); bg = skinProperties.getColor("color.sidebar.bg"); fg = skinProperties.getColor("color.sidebar.fg"); tree.setBackground(bg); tree.setForeground(fg); FontData[] fontData = tree.getFont().getFontData(); int fontHeight = (Constants.isOSX ? 11 : 12) + (tree.getItemHeight() > 18 ? tree.getItemHeight() - 18 : 0); fontData[0].setStyle(SWT.BOLD); FontUtils.getFontHeightFromPX(tree.getDisplay(), fontData, null, fontHeight); fontHeader = new Font(tree.getDisplay(), fontData); font = FontUtils.getFontWithHeight(tree.getFont(), null, fontHeight); tree.setFont(font); Listener treeListener = new Listener() { TreeItem lastTopItem = null; boolean mouseDowned = false; private boolean wasExpanded; public void handleEvent(final Event event) { TreeItem treeItem = (TreeItem) event.item; try { switch (event.type) { case SWT.MeasureItem: { int clientWidth = tree.getClientArea().width; String text = treeItem.getText(event.index); Point size = event.gc.textExtent(text); if (event.x + event.width < clientWidth) { event.width = size.x + event.x; // tree.getClientArea().width; event.x = 0; } if (Constants.isWindows) { event.width = clientWidth - event.x; } event.height = 20; break; } case SWT.PaintItem: { if (USE_PAINTITEM) { SideBarEntrySWT entry = (SideBarEntrySWT) treeItem.getData("MdiEntry"); //System.out.println("PaintItem: " + event.item + ";" + event.index + ";" + event.detail + ";" + id + ";" + event.getBounds() + ";" + event.gc.getClipping()); if (entry != null) { boolean selected = currentEntry == entry && entry.isSelectable(); if (!selected) { event.detail &= ~SWT.SELECTED; } else { event.detail |= SWT.SELECTED; } entry.swt_paintSideBar(event); } } break; } case SWT.Paint: { if (HIDE_NATIVE_EXPANDER) { boolean selected = (event.detail & SWT.SELECTED) > 0; Rectangle bounds = event.getBounds(); int indent = END_INDENT ? tree.getClientArea().width - 1 : 0; int y = event.y + 1; treeItem = tree.getItem(new Point(indent, y)); while (treeItem != null) { SideBarEntrySWT entry = (SideBarEntrySWT) treeItem.getData("MdiEntry"); Rectangle itemBounds = entry.swt_getBounds(); if (itemBounds != null && entry.isCollapseDisabled()) { Rectangle paintArea = treeItem.getBounds(); paintArea.x = 0; paintArea.width = 17; selected = tree.getSelectionCount() == 1 && tree.getSelection()[0].equals(treeItem); int detail = 0; if (selected) { detail |= SWT.SELECTED; } entry.swt_paintEntryBG(detail, event.gc, paintArea); y = itemBounds.y + itemBounds.height + 1; } else { y += tree.getItemHeight(); } if (y > bounds.y + bounds.height) { break; } treeItem = tree.getItem(new Point(indent, y)); } } //System.out.println("Paint: " + event.getBounds() + ";" + event.detail + ";" + event.index + ";" + event.gc.getClipping() + " " + Debug.getCompressedStackTrace()); if (!USE_PAINT) { return; } Rectangle bounds = event.getBounds(); int indent = END_INDENT ? tree.getClientArea().width - 1 : 0; int y = event.y + 1; treeItem = tree.getItem(new Point(indent, y)); while (treeItem != null) { SideBarEntrySWT entry = (SideBarEntrySWT) treeItem.getData("MdiEntry"); Rectangle itemBounds = entry == null ? null : entry.swt_getBounds(); // null itemBounds is weird, the entry must be disposed. it // happened once, so let's check.. if (itemBounds != null) { event.item = treeItem; boolean selected = currentEntry == entry && entry.isSelectable(); event.detail = selected ? SWT.SELECTED : SWT.NONE; Rectangle newClip = bounds.intersection(itemBounds); //System.out.println("Paint " + id + " @ " + newClip); event.setBounds(newClip); event.gc.setClipping(newClip); entry.swt_paintSideBar(event); y = itemBounds.y + itemBounds.height + 1; } else { y += tree.getItemHeight(); } if (y > bounds.y + bounds.height) { break; } TreeItem oldTreeItem = treeItem; treeItem = tree.getItem(new Point(indent, y)); if (oldTreeItem == treeItem) { break; } } if (tree.getTopItem() != lastTopItem) { lastTopItem = tree.getTopItem(); SideBarEntrySWT[] sideBarEntries = (SideBarEntrySWT[]) mapIdToEntry.values().toArray( new SideBarEntrySWT[0]); swt_updateSideBarHitAreasY(sideBarEntries); } break; } case SWT.EraseItem: { SideBarEntrySWT entry = (SideBarEntrySWT) treeItem.getData("MdiEntry"); if (entry == null) { event.detail = 0; } //event.detail &= ~SWT.FOREGROUND; //event.detail &= ~(SWT.FOREGROUND | SWT.BACKGROUND); event.doit = true; break; } case SWT.Resize: { tree.redraw(); break; } case SWT.Selection: { if (treeItem == null) { return; } SideBarEntrySWT entry = (SideBarEntrySWT) treeItem.getData("MdiEntry"); if (entry != null && entry.isSelectable()) { showEntry(entry); } else if (currentEntry != null) { TreeItem topItem = tree.getTopItem(); // prevent "jumping" in the case where selection is off screen // setSelection would jump the item on screen, and then // showItem would jump back to where the user was. tree.setRedraw(false); TreeItem ti = ((SideBarEntrySWT) currentEntry).getTreeItem(); if (ti != null) { tree.setSelection(ti); } tree.setTopItem(topItem); tree.setRedraw(true); event.doit = false; } break; } case SWT.MouseMove: { int indent = END_INDENT ? tree.getClientArea().width - 1 : 0; treeItem = tree.getItem(new Point(indent, event.y)); SideBarEntrySWT entry = (SideBarEntrySWT) (treeItem == null ? null : treeItem.getData("MdiEntry")); int cursorNo = SWT.CURSOR_ARROW; if (treeItem != null) { Rectangle closeArea = (Rectangle) treeItem.getData("closeArea"); if (closeArea != null && closeArea.contains(event.x, event.y)) { cursorNo = SWT.CURSOR_HAND; } else if (entry != null && !entry.isCollapseDisabled() && treeItem.getItemCount() > 0) { cursorNo = SWT.CURSOR_HAND; } } Cursor cursor = event.display.getSystemCursor(cursorNo); if (tree.getCursor() != cursor) { tree.setCursor(cursor); } if (treeItem != null) { wasExpanded = entry != null && entry.isExpanded(); } else { wasExpanded = false; } break; } case SWT.MouseDown: { mouseDowned = true; break; } case SWT.MouseUp: { if (!mouseDowned) { return; } mouseDowned = false; if (tree.getItemCount() == 0 || event.button != 1) { return; } int indent = END_INDENT ? tree.getClientArea().width - 1 : 0; treeItem = tree.getItem(new Point(indent, event.y)); if (treeItem == null) { return; } SideBarEntrySWT entry = (SideBarEntrySWT) treeItem.getData("MdiEntry"); Rectangle closeArea = (Rectangle) treeItem.getData("closeArea"); if (closeArea != null && closeArea.contains(event.x, event.y)) { treeItem.dispose(); return; } else if (currentEntry != entry && Constants.isOSX) { showEntry(entry); } if (entry != null) { MdiEntryVitalityImage[] vitalityImages = entry.getVitalityImages(); for (int i = 0; i < vitalityImages.length; i++) { SideBarVitalityImageSWT vitalityImage = (SideBarVitalityImageSWT) vitalityImages[i]; if (vitalityImage == null || !vitalityImage.isVisible()) { continue; } Rectangle hitArea = vitalityImage.getHitArea(); if (hitArea == null) { continue; } // setHitArea needs it relative to entry Rectangle itemBounds = entry.swt_getBounds(); int relY = event.y - (itemBounds == null ? 0 : itemBounds.y); if (hitArea.contains(event.x, relY)) { vitalityImage.triggerClickedListeners(event.x, relY); return; } } if (!entry.isCollapseDisabled() && treeItem.getItemCount() > 0) { MdiEntry currentEntry = getCurrentEntry(); if (currentEntry != null && entry.getId().equals(currentEntry.getParentID())) { showEntryByID(SIDEBAR_SECTION_LIBRARY); } entry.setExpanded(!wasExpanded); wasExpanded = !wasExpanded; } } break; } case SWT.Dispose: { fontHeader.dispose(); font.dispose(); if (dropTarget != null && !dropTarget.isDisposed()) { dropTarget.dispose(); } saveCloseables(); break; } case SWT.Collapse: { SideBarEntrySWT entry = (SideBarEntrySWT) treeItem.getData("MdiEntry"); if (entry.isCollapseDisabled()) { tree.setRedraw(false); Display.getDefault().asyncExec(new Runnable() { public void run() { ((TreeItem) event.item).setExpanded(true); tree.setRedraw(true); } }); } else { MdiEntry currentEntry = getCurrentEntry(); if (currentEntry != null && entry.getId().equals(currentEntry.getParentID())) { showEntryByID(SIDEBAR_SECTION_LIBRARY); } } break; } } } catch (Exception e) { Debug.out(e); } } }; tree.addListener(SWT.MeasureItem, treeListener); tree.addListener(SWT.Resize, treeListener); tree.addListener(SWT.Paint, treeListener); if (USE_PAINTITEM) { tree.addListener(SWT.PaintItem, treeListener); tree.addListener(SWT.EraseItem, treeListener); } tree.addListener(SWT.Selection, treeListener); tree.addListener(SWT.Dispose, treeListener); // For icons tree.addListener(SWT.MouseUp, treeListener); tree.addListener(SWT.MouseDown, treeListener); // For cursor tree.addListener(SWT.MouseMove, treeListener); // to disable collapsing tree.addListener(SWT.Collapse, treeListener); dropTarget = new DropTarget(tree, DND.DROP_COPY); dropTarget.setTransfer(new Transfer[] { URLTransfer.getInstance(), FileTransfer.getInstance(), TextTransfer.getInstance(), }); dropTarget.addDropListener(new DropTargetAdapter() { public void dropAccept(DropTargetEvent event) { event.currentDataType = URLTransfer.pickBestType(event.dataTypes, event.currentDataType); } public void dragEnter(DropTargetEvent event) { } public void dragOperationChanged(DropTargetEvent event) { } // @see org.eclipse.swt.dnd.DropTargetAdapter#dragOver(org.eclipse.swt.dnd.DropTargetEvent) public void dragOver(DropTargetEvent event) { TreeItem treeItem = (event.item instanceof TreeItem) ? (TreeItem) event.item : null; if (treeItem != null) { SideBarEntrySWT entry = (SideBarEntrySWT) treeItem.getData("MdiEntry"); draggingOver = entry; } else { draggingOver = null; } if (draggingOver == null || !draggingOver.hasDropListeners()) { boolean isTorrent = TorrentOpener.doesDropHaveTorrents(event); if (isTorrent) { event.detail = DND.DROP_COPY; } else { event.detail = DND.DROP_NONE; } draggingOver = null; } else if ((event.operations & DND.DROP_LINK) > 0) event.detail = DND.DROP_LINK; else if ((event.operations & DND.DROP_COPY) > 0) event.detail = DND.DROP_COPY; else if ((event.operations & DND.DROP_DEFAULT) > 0) event.detail = DND.DROP_COPY; if (Constants.isOSX) { tree.redraw(); } } // @see org.eclipse.swt.dnd.DropTargetAdapter#dragLeave(org.eclipse.swt.dnd.DropTargetEvent) public void dragLeave(DropTargetEvent event) { draggingOver = null; tree.redraw(); } public void drop(DropTargetEvent event) { draggingOver = null; tree.redraw(); if (!(event.item instanceof TreeItem)) { defaultDrop(event); return; } TreeItem treeItem = (TreeItem) event.item; SideBarEntrySWT entry = (SideBarEntrySWT) treeItem.getData("MdiEntry"); boolean handled = entry.triggerDropListeners(event.data); if (!handled) { defaultDrop(event); } } }); final Menu menuTree = new Menu(tree); tree.setMenu(menuTree); menuTree.addMenuListener(new MenuListener() { boolean bShown = false; public void menuHidden(MenuEvent e) { bShown = false; if (Constants.isOSX) { return; } // Must dispose in an asyncExec, otherwise SWT.Selection doesn't // get fired (async workaround provided by Eclipse Bug #87678) Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { if (bShown || menuTree.isDisposed()) { return; } Utils.disposeSWTObjects(menuTree.getItems()); } }); } public void menuShown(MenuEvent e) { Utils.disposeSWTObjects(menuTree.getItems()); bShown = true; Point ptMouse = tree.toControl(e.display.getCursorLocation()); int indent = END_INDENT ? tree.getClientArea().width - 1 : 0; TreeItem treeItem = tree.getItem(new Point(indent, ptMouse.y)); if (treeItem == null) { return; } SideBarEntrySWT entry = (SideBarEntrySWT) treeItem.getData("MdiEntry"); fillMenu(menuTree, entry); if (menuTree.getItemCount() == 0) { Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { menuTree.setVisible(false); } }); } } }); if (soSideBarPopout != null) { SWTSkinObject soDropDown = skin.getSkinObject("sidebar-dropdown"); if (soDropDown != null) { final Menu menuDropDown = new Menu(soDropDown.getControl()); menuDropDown.addMenuListener(new MenuListener() { boolean bShown = false; public void menuHidden(MenuEvent e) { bShown = false; if (Constants.isOSX) { return; } // Must dispose in an asyncExec, otherwise SWT.Selection doesn't // get fired (async workaround provided by Eclipse Bug #87678) Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { if (bShown || menuDropDown.isDisposed()) { return; } Utils.disposeSWTObjects(menuDropDown.getItems()); } }); } public void menuShown(MenuEvent e) { Utils.disposeSWTObjects(menuDropDown.getItems()); bShown = true; fillDropDownMenu(menuDropDown, tree.getItems(), 0); } }); dropDownSelectionListener = new SelectionListener() { public void widgetSelected(SelectionEvent e) { String id = (String) e.widget.getData("Plugin.viewID"); showEntryByID(id); } public void widgetDefaultSelected(SelectionEvent e) { } }; SWTSkinButtonUtility btnDropDown = new SWTSkinButtonUtility(soDropDown); btnDropDown.addSelectionListener(new ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { Control c = buttonUtility.getSkinObject().getControl(); menuDropDown.setLocation(c.getDisplay().getCursorLocation()); menuDropDown.setVisible(!menuDropDown.getVisible()); } }); } SWTSkinObject soExpand = skin.getSkinObject("sidebar-expand"); if (soExpand != null) { SWTSkinButtonUtility btnExpand = new SWTSkinButtonUtility(soExpand); btnExpand.addSelectionListener(new ButtonListenerAdapter() { public void pressed(SWTSkinButtonUtility buttonUtility, SWTSkinObject skinObject, int stateMask) { flipSideBarVisibility(); } }); } } } /** * @param event */ protected void defaultDrop(DropTargetEvent event) { TorrentOpener.openDroppedTorrents(event, false); } /** * @param menuDropDown * * @since 3.1.1.1 */ protected void fillDropDownMenu(Menu menuDropDown, TreeItem[] items, int indent) { String s = ""; for (int i = 0; i < indent; i++) { s += " "; } for (int i = 0; i < items.length; i++) { TreeItem treeItem = items[i]; org.eclipse.swt.widgets.MenuItem menuItem = new org.eclipse.swt.widgets.MenuItem( menuDropDown, SWT.RADIO); SideBarEntrySWT entry = (SideBarEntrySWT) treeItem.getData("MdiEntry"); if (entry == null) { continue; } String id = entry.getId(); menuItem.setData("Plugin.viewID", id); ViewTitleInfo titleInfo = entry.getViewTitleInfo(); String ind = ""; if (titleInfo != null) { String o = (String) titleInfo.getTitleInfoProperty(ViewTitleInfo.TITLE_INDICATOR_TEXT); if (o != null) { ind = " (" + o + ")"; //ind = "\t" + o; } } menuItem.setText(s + entry.getTitle() + ind); menuItem.addSelectionListener(dropDownSelectionListener); if (currentEntry != null && currentEntry.getId().equals(id)) { menuItem.setSelection(true); } TreeItem[] subItems = treeItem.getItems(); if (subItems.length > 0) { fillDropDownMenu(menuDropDown, subItems, indent + 1); } } } /** * @param menuTree * * @since 3.1.0.1 */ protected void fillMenu(Menu menuTree, final MdiEntry entry) { org.gudy.azureus2.plugins.ui.menus.MenuItem[] menu_items; menu_items = MenuItemManager.getInstance().getAllAsArray("sidebar"); MenuBuildUtils.addPluginMenuItems((Composite) soMain.getControl(), menu_items, menuTree, false, true, new MenuBuildUtils.MenuItemPluginMenuControllerImpl(new Object[] { entry })); if (entry != null) { menu_items = MenuItemManager.getInstance().getAllAsArray( "sidebar." + entry.getId()); if (menu_items.length == 0) { if (entry instanceof SideBarEntrySWT) { IView view = ((SideBarEntrySWT) entry).getIView(); if (view instanceof UISWTView) { PluginInterface pi = ((UISWTView) view).getPluginInterface(); if (pi != null) { final List<String> relevant_sections = new ArrayList<String>(); List<ConfigSectionHolder> sections = ConfigSectionRepository.getInstance().getHolderList(); for (ConfigSectionHolder cs : sections) { if (pi == cs.getPluginInterface()) { relevant_sections.add(cs.configSectionGetName()); } } if (relevant_sections.size() > 0) { MenuItem mi = pi.getUIManager().getMenuManager().addMenuItem( "sidebar." + entry.getId(), "MainWindow.menu.view.configuration"); mi.addListener(new MenuItemListener() { public void selected(MenuItem menu, Object target) { UIFunctions uif = UIFunctionsManager.getUIFunctions(); if (uif != null) { for (String s : relevant_sections) { uif.openView(UIFunctions.VIEW_CONFIG, s); } } } }); menu_items = MenuItemManager.getInstance().getAllAsArray( "sidebar." + entry.getId()); } } } } } MenuBuildUtils.addPluginMenuItems((Composite) soMain.getControl(), menu_items, menuTree, false, true, new MenuBuildUtils.MenuItemPluginMenuControllerImpl(new Object[] { entry })); MdiSWTMenuHackListener[] menuHackListeners = getMenuHackListeners(); for (MdiSWTMenuHackListener l : menuHackListeners) { try { l.menuWillBeShown(entry, menuTree); } catch (Exception e) { Debug.out(e); } } if (currentEntry instanceof SideBarEntrySWT) { menuHackListeners = ((SideBarEntrySWT) entry).getMenuHackListeners(); for (MdiSWTMenuHackListener l : menuHackListeners) { try { l.menuWillBeShown(entry, menuTree); } catch (Exception e) { Debug.out(e); } } } } } public void addListener(MdiSWTMenuHackListener l) { synchronized (this) { if (listMenuHackListners == null) { listMenuHackListners = new ArrayList<MdiSWTMenuHackListener>(1); } if (!listMenuHackListners.contains(l)) { listMenuHackListners.add(l); } } } public void removeListener(MdiSWTMenuHackListener l) { synchronized (this) { if (listMenuHackListners == null) { listMenuHackListners = new ArrayList<MdiSWTMenuHackListener>(1); } listMenuHackListners.remove(l); } } public MdiSWTMenuHackListener[] getMenuHackListeners() { synchronized (this) { if (listMenuHackListners == null) { return new MdiSWTMenuHackListener[0]; } return listMenuHackListners.toArray(new MdiSWTMenuHackListener[0]); } } /** * * * @since 3.1.1.1 */ private void swt_updateSideBarHitAreasY(SideBarEntrySWT[] entries) { for (int x = 0; x < entries.length; x++) { SideBarEntrySWT entry = entries[x]; TreeItem treeItem = entry.getTreeItem(); if (treeItem == null || treeItem.isDisposed()) { continue; } Rectangle itemBounds = entry.swt_getBounds(); if (entry.isCloseable()) { Rectangle closeArea = (Rectangle) treeItem.getData("closeArea"); if (closeArea != null) { closeArea.y = itemBounds.y + (itemBounds.height - closeArea.height) / 2; } } MdiEntryVitalityImage[] vitalityImages = entry.getVitalityImages(); for (int i = 0; i < vitalityImages.length; i++) { SideBarVitalityImageSWT vitalityImage = (SideBarVitalityImageSWT) vitalityImages[i]; if (!vitalityImage.isVisible()) { continue; } Image image = vitalityImage.getImage(); if (image != null) { Rectangle bounds = vitalityImage.getHitArea(); if (bounds == null) { continue; } bounds.y = (itemBounds.height - bounds.height) / 2; } } } } protected int indexOf(final MdiEntry entryLibrary) { Object o = Utils.execSWTThreadWithObject("indexOf", new AERunnableObject() { public Object runSupport() { TreeItem treeItem = ((SideBarEntrySWT) entryLibrary).getTreeItem(); if (treeItem == null) { return -1; } TreeItem parentItem = treeItem.getParentItem(); if (parentItem != null) { return parentItem.indexOf(treeItem); } return tree.indexOf(treeItem); } }, 500); if (o instanceof Number) { return ((Number) o).intValue(); } return -1; } public MdiEntry createHeader(String id, String title, String preferredAfterID) { MdiEntry oldEntry = getEntry(id); if (oldEntry != null) { return oldEntry; } SideBarEntrySWT entry = new SideBarEntrySWT(this, skin, id); entry.setSelectable(false); entry.setPreferredAfterID(preferredAfterID); entry.setTitle(title); setupNewEntry(entry, id, true, false); return entry; } public MdiEntry createEntryFromIView(String parentID, IView iview, String id, Object datasource, boolean closeable, boolean show, boolean expand) { if (id == null) { id = iview.getClass().getName(); int i = id.lastIndexOf('.'); if (i > 0) { id = id.substring(i + 1); } } MdiEntry oldEntry = getEntry(id); if (oldEntry != null) { if (show) { showEntry(oldEntry); } return oldEntry; } SideBarEntrySWT entry = new SideBarEntrySWT(this, skin, id); entry.setIView(iview); entry.setDatasource(datasource); entry.setParentID(parentID); setupNewEntry(entry, id, expand, closeable); if (iview instanceof IViewAlwaysInitialize) { entry.build(); } if (show) { showEntry(entry); } return entry; } private void setupNewEntry(final SideBarEntrySWT entry, final String id, final boolean expandParent, final boolean closeable) { //System.out.println("createItem " + id + ";" + Debug.getCompressedStackTrace()); synchronized (mapIdToEntry) { mapIdToEntry.put(id, entry); } entry.setCloseable(closeable); entry.setParentSkinObject(soSideBarContents); if (SIDEBAR_HEADER_PLUGINS.equals(entry.getParentID()) && entry.getImageLeftID() == null) { entry.setImageLeftID("image.sidebar.plugin"); } Utils.execSWTThreadLater(0, new AERunnable() { public void runSupport() { _setupNewEntry(entry, id, expandParent, closeable); } }); } protected void _setupNewEntry(SideBarEntrySWT entry, String id, boolean expandParent, boolean closeable) { String parentID = entry.getParentID(); MdiEntry parent = getEntry(parentID); TreeItem parentTreeItem = null; if (parent instanceof SideBarEntrySWT) { SideBarEntrySWT parentSWT = (SideBarEntrySWT) parent; parentTreeItem = parentSWT.getTreeItem(); if (expandParent) { parentTreeItem.setExpanded(true); } } int index = -1; String preferredAfterID = entry.getPreferredAfterID(); if (preferredAfterID != null) { if (preferredAfterID.length() == 0) { index = 0; } else { MdiEntry entryAbove = getEntry(preferredAfterID); if (entryAbove != null) { index = indexOf(entryAbove); if (index >= 0) { index++; } //System.out.println("ENTRY " + id + " is going to go below " + entryAbove.getId() + " at " + index); } } } if (index == -1 && parent == null) { index = 0; String[] order = getPreferredOrder(); for (int i = 0; i < order.length; i++) { String orderID = order[i]; if (orderID.equals(id)) { break; } MdiEntry entry2 = getEntry(orderID); if (entry2 != null) { int i2 = indexOf(entry2); if (i2 >= 0) { index = i2 + 1; } } } if (index >= order.length) { index = -1; } } if (GAP_BETWEEN_LEVEL_1 && parentTreeItem == null && tree.getItemCount() > 0 && index != 0) { createTreeItem(null, index); if (index >= 0) { index++; } } TreeItem treeItem = createTreeItem(parentTreeItem, index); if (treeItem != null) { treeItem.setData("MdiEntry", entry); entry.setTreeItem(treeItem); triggerEntryLoadedListeners(entry); } if (GAP_BETWEEN_LEVEL_1 && parentTreeItem == null && tree.getItemCount() > 1 && index == 0) { createTreeItem(null, ++index); } } /* (non-Javadoc) * @see com.aelitis.azureus.ui.swt.mdi.BaseMDI#createEntryFromIViewClass(java.lang.String, java.lang.String, java.lang.String, java.lang.Class, java.lang.Class<?>[], java.lang.Object[], java.lang.Object, com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo, boolean) */ public MdiEntry createEntryFromIViewClass(String parent, String id, String title, Class<?> iviewClass, Class<?>[] iviewClassArgs, Object[] iviewClassVals, Object datasource, ViewTitleInfo titleInfo, boolean closeable) { MdiEntry oldEntry = getEntry(id); if (oldEntry != null) { return oldEntry; } SideBarEntrySWT entry = new SideBarEntrySWT(this, skin, id); entry.setTitle(title); entry.setIViewClass(iviewClass, iviewClassArgs, iviewClassVals); entry.setDatasource(datasource); entry.setViewTitleInfo(titleInfo); entry.setParentID(parent); setupNewEntry(entry, id, false, closeable); if (IViewAlwaysInitialize.class.isAssignableFrom(iviewClass)) { entry.build(); } return entry; } private TreeItem createTreeItem(Object parentSwtItem, int index) { TreeItem treeItem; if (parentSwtItem == null) { parentSwtItem = tree; } if (parentSwtItem instanceof Tree) { Tree tree = (Tree) parentSwtItem; if (tree.isDisposed()) { return null; } if (index >= 0 && index < tree.getItemCount()) { treeItem = new TreeItem(tree, SWT.NONE, index); } else { treeItem = new TreeItem(tree, SWT.NONE); } } else { if (((TreeItem) parentSwtItem).isDisposed()) { return null; } if (index >= 0 && index < ((TreeItem) parentSwtItem).getItemCount()) { treeItem = new TreeItem((TreeItem) parentSwtItem, SWT.NONE, index); } else { treeItem = new TreeItem((TreeItem) parentSwtItem, SWT.NONE); } } return treeItem; } public void showEntry(MdiEntry newEntry) { if (tree.isDisposed()) { return; } if (newEntry == null || !newEntry.isSelectable()) { return; } final SideBarEntrySWT oldEntry = (SideBarEntrySWT) currentEntry; //System.out.println("showEntry " + newEntry.getId() + "; was " + (oldEntry == null ? "null" : oldEntry.getId())); if (currentEntry == newEntry) { triggerSelectionListener(newEntry, newEntry); return; } // show new currentEntry = (MdiEntrySWT) newEntry; if (oldEntry != null && oldEntry != newEntry) { oldEntry.redraw(); } if (currentEntry != null) { ((BaseMdiEntry) currentEntry).show(); } // hide old if (oldEntry != null && oldEntry != newEntry) { oldEntry.hide(); oldEntry.redraw(); } newEntry.redraw(); triggerSelectionListener(newEntry, oldEntry); } /** * @see com.aelitis.azureus.ui.swt.mdi.BaseMDI#createEntryFromEventListener(java.lang.String, org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener, java.lang.String, boolean, java.lang.Object) */ public MdiEntry createEntryFromEventListener(String parentID, UISWTViewEventListener l, String id, boolean closeable, Object datasource) { MdiEntry oldEntry = getEntry(id); if (oldEntry != null) { return oldEntry; } SideBarEntrySWT entry = new SideBarEntrySWT(this, skin, id); try { // hack: setEventListner will create the UISWTView. // We need to have the entry available for the view to use // if it wants synchronized (mapIdToEntry) { mapIdToEntry.put(id, entry); } entry.setParentID(parentID); entry.setDatasource(datasource); setupNewEntry(entry, id, false, closeable); entry.setEventListener(l); } catch (Exception e) { Debug.out(e); entry.close(true); } return entry; } /* (non-Javadoc) * @see com.aelitis.azureus.ui.swt.mdi.BaseMDI#createEntryFromSkinRef(java.lang.String, java.lang.String, java.lang.String, java.lang.String, com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo, java.lang.Object, boolean, int) */ public MdiEntry createEntryFromSkinRef(String parentID, final String id, final String configID, String title, ViewTitleInfo titleInfo, final Object params, boolean closeable, int index) { return createEntryFromSkinRef(parentID, id, configID, title, titleInfo, params, closeable, index == 0 ? "" : null); } // @see com.aelitis.azureus.ui.swt.mdi.BaseMDI#createEntryFromSkinRef(java.lang.String, java.lang.String, java.lang.String, java.lang.String, com.aelitis.azureus.ui.common.viewtitleinfo.ViewTitleInfo, java.lang.Object, boolean, java.lang.String) public MdiEntry createEntryFromSkinRef(String parentID, String id, String configID, String title, ViewTitleInfo titleInfo, Object params, boolean closeable, String preferredAfterID) { MdiEntry oldEntry = getEntry(id); if (oldEntry != null) { return oldEntry; } SideBarEntrySWT entry = new SideBarEntrySWT(this, skin, id); entry.setTitle(title); entry.setSkinRef(configID, params); entry.setParentID(parentID); entry.setViewTitleInfo(titleInfo); entry.setPreferredAfterID(preferredAfterID); setupNewEntry(entry, id, false, closeable); return entry; } // @see com.aelitis.azureus.ui.swt.utils.UIUpdatable#updateUI() public void updateUI() { if (currentEntry == null || currentEntry.getIView() == null || tree.getSelectionCount() == 0) { return; } currentEntry.updateUI(); } public boolean showEntryByID(String id) { return loadEntryByID(id, true); } public boolean loadEntryByID(String id, boolean activate) { return loadEntryByID(id, activate, false); } public boolean loadEntryByID(String id, boolean activate, boolean onlyLoadOnce) { if (id == null) { return false; } MdiEntry entry = getEntry(id); if (entry != null) { if (activate) { showEntry(entry); } return true; } boolean loadedOnce = COConfigurationManager.getBooleanParameter("sb.once." + id, false); if (loadedOnce && onlyLoadOnce) { return false; } if (id.equals(SIDEBAR_SECTION_WELCOME)) { SideBarEntrySWT entryWelcome = (SideBarEntrySWT) createWelcomeSection(); if (activate) { showEntry(entryWelcome); } return true; } else if (id.startsWith("ContentNetwork.")) { long networkID = Long.parseLong(id.substring(15)); handleContentNetworkSwitch(id, networkID); return true; } else if (id.equals("library") || id.equals("minilibrary")) { id = SIDEBAR_SECTION_LIBRARY; loadEntryByID(id, activate); return true; } else if (id.equals("activities")) { id = SIDEBAR_SECTION_ACTIVITIES; loadEntryByID(id, activate); return true; } MdiEntryCreationListener mdiEntryCreationListener = mapIdToCreationListener.get(id); if (mdiEntryCreationListener != null) { MdiEntry mdiEntry = mdiEntryCreationListener.createMDiEntry(id); if (mdiEntry instanceof SideBarEntrySWT) { if (onlyLoadOnce) { COConfigurationManager.setParameter("sb.once." + id, true); } if (activate) { showEntry(mdiEntry); } return true; } } else { setEntryAutoOpen(id, true); } return false; } /** * @param tabID * * @since 4.0.0.3 */ protected void handleContentNetworkSwitch(String tabID, long networkID) { String defaultID = ContentNetworkUtils.getTarget(ConstantsVuze.getDefaultContentNetwork()); try { ContentNetworkManager cnManager = ContentNetworkManagerFactory.getSingleton(); if (cnManager == null) { showEntryByID(defaultID); return; } ContentNetwork cn = cnManager.getContentNetwork(networkID); if (cn == null) { showEntryByID(defaultID); return; } if (networkID == ContentNetwork.CONTENT_NETWORK_VUZE) { showEntryByID(defaultID); cn.setPersistentProperty(ContentNetwork.PP_ACTIVE, Boolean.TRUE); return; } boolean doneAuth = false; Object oDoneAuth = cn.getPersistentProperty(ContentNetwork.PP_AUTH_PAGE_SHOWN); if (oDoneAuth instanceof Boolean) { doneAuth = ((Boolean) oDoneAuth).booleanValue(); } if (!doneAuth && cn.isServiceSupported(ContentNetwork.SERVICE_AUTHORIZE)) { if (!AuthorizeWindow.openAuthorizeWindow(cn)) { return; } } createContentNetworkSideBarEntry(cn); showEntryByID(tabID); return; } catch (Exception e) { Debug.out(e); } showEntryByID(defaultID); } private void createContentNetworkSideBarEntry(ContentNetwork cn) { String entryID = ContentNetworkUtils.getTarget(cn); if (entryExists(entryID)) { return; } String name = cn.getName(); SideBarEntrySWT entryBrowse = (SideBarEntrySWT) getEntry(ContentNetworkUtils.getTarget(ConstantsVuze.getDefaultContentNetwork())); int position = entryBrowse == null || entryBrowse.getTreeItem() == null ? 3 : tree.indexOf(entryBrowse.getTreeItem()) + 1; Object prop = cn.getProperty(ContentNetwork.PROPERTY_REMOVEABLE); boolean closeable = (prop instanceof Boolean) ? ((Boolean) prop).booleanValue() : false; final SideBarEntrySWT entry = (SideBarEntrySWT) createEntryFromSkinRef( SIDEBAR_HEADER_VUZE, entryID, "main.area.browsetab", name, null, cn, closeable, position); ContentNetworkUI.loadImage(cn.getID(), new ContentNetworkImageLoadedListener() { public void contentNetworkImageLoaded(Long contentNetworkID, Image image, boolean wasReturned) { entry.setImageLeft(image); } }); cn.setPersistentProperty(ContentNetwork.PP_ACTIVE, Boolean.TRUE); cn.setPersistentProperty(ContentNetwork.PP_SHOW_IN_MENU, Boolean.TRUE); } public Font getHeaderFont() { return fontHeader; } protected Tree getTree() { return tree; } // @see com.aelitis.azureus.ui.swt.mdi.MultipleDocumentInterfaceSWT#getEntryFromSkinObject(org.gudy.azureus2.ui.swt.plugins.PluginUISWTSkinObject) public MdiEntrySWT getEntryFromSkinObject( PluginUISWTSkinObject pluginSkinObject) { if (pluginSkinObject instanceof SWTSkinObject) { Control control = ((SWTSkinObject) pluginSkinObject).getControl(); while (control != null && !control.isDisposed()) { Object entry = control.getData("BaseMDIEntry"); if (entry instanceof BaseMdiEntry) { BaseMdiEntry mdiEntry = (BaseMdiEntry) entry; return mdiEntry; } control = control.getParent(); } } return null; } }