/* * Copyright (c) 2003-2004, KNOPFLERFISH project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * - Neither the name of the KNOPFLERFISH project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.knopflerfish.bundle.desktopawt; import org.osgi.framework.*; import org.osgi.service.packageadmin.*; import java.awt.*; import java.awt.event.*; import java.util.*; class DesktopPanel extends Panel implements BundleListener { ScrollPane scroll; Toolbar toolbar; Container bundlePanel; Panel cardPanel; CardLayout cardLayout; Console console; StatusBar statusBar; Container openPanel; public static final int SORT_ID = 0; public static final int SORT_NAME = 1; public static final int SORT_STATE = 2; int sortMode = SORT_ID; Hashtable bundles = new Hashtable(); LF lf = LF.getLF(); DesktopPanel() { super(); setLayout(new BorderLayout()); scroll = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED); scroll.setSize(new Dimension(250, 300)); cardLayout = new CardLayout(); cardPanel = new Panel(); cardPanel.setLayout(cardLayout); bundlePanel = new Panel(); bundlePanel.setLayout(new GridLayout(0,1)); console = new Console(); console.panel.text.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent ev) { String s = console.panel.text.getSelectedText(); selectBundleFromText(s); } }); openPanel = new InstallPanel(); // bundlePanel.setSize(new Dimension(200, 400)); toolbar = new Toolbar(); scroll.add(bundlePanel); cardPanel.add(scroll, "bundles"); cardLayout.addLayoutComponent("bundles", scroll); cardPanel.add(console.panel, "console"); cardLayout.addLayoutComponent("console", console.panel); cardPanel.add(openPanel, "open"); cardLayout.addLayoutComponent("open", openPanel); statusBar = new StatusBar(); add(cardPanel, BorderLayout.CENTER); add(toolbar, BorderLayout.NORTH); add(statusBar, BorderLayout.SOUTH); setBackground(lf.bgColor); bundlePanel.setBackground(Color.white); Activator.bc.addBundleListener(this); Bundle[] bl = Activator.bc.getBundles(); for(int i = 0; bl != null && i < bl.length; i++) { this.bundleChanged(new BundleEvent(BundleEvent.INSTALLED, bl[i])); } // This will sort all displayed bundles showBundles(sortMode); } public void bundleChanged(BundleEvent ev) { switch(ev.getType()) { case BundleEvent.INSTALLED: addBundle(ev.getBundle()); rebuildBundles(); break; case BundleEvent.UNINSTALLED: removeBundle(ev.getBundle()); rebuildBundles(); break; } // System.out.println(ev.getBundle() + ", " + ev.getType()); bundleUpdated(ev.getBundle()); } public void removeBundle(Bundle b) { synchronized(bundles) { BundleC bc = (BundleC)bundles.get(b); if(bc != null) { bundles.remove(b); rebuildBundles(); } } } public void addBundle(Bundle b) { synchronized(bundles) { if(!bundles.containsKey(b)) { BundleC bc = new BundleC(b); bundles.put(b, bc); rebuildBundles(); } } } void insertBundle(Vector v, Bundle b, Comp comp) { for(int i = 0; i < v.size(); i++) { Bundle b0 = (Bundle)v.elementAt(i); if(comp.compare(b, b0) <= 0) { v.insertElementAt(b, i); return; } } v.addElement(b); } void rebuildBundles() { synchronized(bundles) { int sort = sortMode; try { Comp comp = compId; if(sort == SORT_ID) { comp = compId; } else if(sort == SORT_NAME) { comp = compName; } else if(sort == SORT_STATE) { comp = compState; } bundlePanel.removeAll(); Vector sorted = new Vector(); for(Enumeration e = bundles.keys(); e.hasMoreElements();) { Bundle b = (Bundle)e.nextElement(); BundleC bc = (BundleC)bundles.get(b); insertBundle(sorted, b, comp); } for(int i = 0; i < sorted.size(); i++) { Bundle b = (Bundle)sorted.elementAt(i); BundleC bc = (BundleC)bundles.get(b); if(bc == null) { bc = new BundleC(b); bundles.put(b, bc); } bundlePanel.add(bc); } invalidate(); bundlePanel.doLayout(); bundlePanel.repaint(); repaint(); } catch (Exception e) { e.printStackTrace(); } } } void bundleUpdated(Bundle b) { BundleC bc = (BundleC)bundles.get(b); if(bc != null) { // System.out.println("update " + bc); bc.bundleUpdated(); } } void unselectAll() { for(Enumeration e = bundles.keys(); e.hasMoreElements();) { Bundle b = (Bundle)e.nextElement(); BundleC bc = (BundleC)bundles.get(b); if(bc.isSelected()) { bc.bFocus = false; bc.setSelected(false); } } } public void startBundles() { if(bundles.size() == 0) { statusBar.setMessage("No bundles selected"); return; } for(Enumeration e = bundles.keys(); e.hasMoreElements();) { Bundle b = (Bundle)e.nextElement(); BundleC bc = (BundleC)bundles.get(b); if(bc.isSelected()) { try { b.start(); } catch (Exception ex) { ex.printStackTrace(); } } } } public void openBundle() { cardLayout.show(cardPanel, "open"); } public void stopBundles() { if(bundles.size() == 0) { statusBar.setMessage("No bundles selected"); return; } for(Enumeration e = bundles.keys(); e.hasMoreElements();) { Bundle b = (Bundle)e.nextElement(); BundleC bc = (BundleC)bundles.get(b); if(bc.isSelected()) { try { b.stop(); } catch (Exception ex) { ex.printStackTrace(); } } } } public void uninstallBundles() { if(bundles.size() == 0) { statusBar.setMessage("No bundles selected"); return; } for(Enumeration e = bundles.keys(); e.hasMoreElements();) { Bundle b = (Bundle)e.nextElement(); BundleC bc = (BundleC)bundles.get(b); if(bc.isSelected()) { try { b.uninstall(); rebuildBundles(); } catch (Exception ex) { ex.printStackTrace(); } } } } public void updateBundles() { if(bundles.size() == 0) { statusBar.setMessage("No bundles selected"); return; } for(Enumeration e = bundles.keys(); e.hasMoreElements();) { Bundle b = (Bundle)e.nextElement(); BundleC bc = (BundleC)bundles.get(b); if(bc.isSelected()) { try { b.update(); } catch (Exception ex) { ex.printStackTrace(); } } } } void selectBundleFromText(String s) { unselectAll(); if(s != null && s.length() > 0) { s = s.trim(); try { long bid = Long.parseLong(s); for(Enumeration e = bundles.keys(); e.hasMoreElements();) { Bundle b = (Bundle)e.nextElement(); BundleC bc = (BundleC)bundles.get(b); if(b.getBundleId() == bid) { bc.setSelected(true); } } } catch (Exception ignore) { } } } void showBundles(int sort) { sortMode = sort; rebuildBundles(); cardLayout.show(cardPanel, "bundles"); } void showConsole() { cardLayout.show(cardPanel, "console"); } void showOBR() { cardLayout.show(cardPanel, "obr"); } void showInstall() { cardLayout.show(cardPanel, "install"); } void showInfo(BundleC bc) { if(bc != null) { } } class BundleC extends DBContainer { boolean bSelected = false; boolean bFocus = false; String lab; String lab2; Bundle b; Image bundleImage; Dimension imgSize; long maxPaintTime = 30; BundleC(Bundle _b) { super(); this.b = _b; bundleImage = Util.hasActivator(b) ? Desktop.bundleImage : Desktop.libImage; imgSize = new Dimension(bundleImage.getWidth(null), bundleImage.getHeight(null)); MouseListener mouseListener = new MouseAdapter() { public void mouseClicked(MouseEvent ev) { unselectAll(); setSelected(true); } public void mouseEntered(MouseEvent ev) { if(paintTime < maxPaintTime) { showInfo(BundleC.this); setFocus(true); } } public void mouseExited(MouseEvent ev) { if(paintTime < maxPaintTime) { showInfo(null); setFocus(false); } } }; lab = Util.getBundleName(b); lab2 = ""; addMouseListener(mouseListener); bundleUpdated(); } Color alphaCol = new Color(0,0,0,255); void paintImage(Graphics g) { Image overlay = null; switch(b.getState()) { case Bundle.ACTIVE: overlay = Desktop.activeIcon; break; case Bundle.INSTALLED: break; case Bundle.RESOLVED: break; case Bundle.STARTING: break; case Bundle.STOPPING: break; case Bundle.UNINSTALLED: break; default: } Dimension size = getSize(); int x = 0; int y = 0; g.drawImage(bundleImage, x, y, null); if(overlay != null) { int w = overlay.getWidth(null); int h = overlay.getHeight(null); int x1 = x + (imgSize.width - w - 2); int y1 = y + (imgSize.height - h - 2); g.drawImage(overlay, x1, y1, alphaCol, null); } } public void paintComponent(Graphics g) { try { count++; // System.out.println(count + ": paintComponent " + b + ", sel=" + bSelected + ", focus=" + bFocus + ", mem=" + (g == memG)); // Thread.sleep(200); } catch (Exception e) { } Dimension size = getSize(); g.setColor(getBackground()); g.fillRect(0,0, size.width, size.height); int left = 2 + bundleImage.getWidth(null); int ypos = 2; paintImage(g); g.setColor(Color.black); g.setFont(lf.defaultFont); ypos += g.getFont().getSize(); g.drawString(lab, left, ypos); ypos += g.getFont().getSize() + 2; g.setColor(Color.gray); g.setFont(lf.smallFont); g.drawString(lab2, left, ypos); ypos += g.getFont().getSize() + 2; long t1 = System.currentTimeMillis(); } public Dimension preferredSize() { return getPreferredSize(); } public Dimension getPreferredSize() { return imgSize; } void bundleUpdated() { int maxLen = 25; String desc = Util.getHeader(b, "Bundle-Description", ""); if(desc == null) { desc = ""; } if(desc.length() > maxLen) { desc = desc.substring(0, maxLen) + "..."; } lab2 = desc + " (#" + b.getBundleId() + ", " + Util.stateName(b.getState()) + ")"; bNeedRedraw = true; repaint(); } public boolean isSelected() { return bSelected; } public void setFocus(boolean b) { if(bFocus == b) { return; } bFocus = b; bNeedRedraw = true; setSelected(isSelected()); } public boolean isFocus() { return bFocus; } public void setSelected(boolean b) { if(bSelected != b) { bNeedRedraw = true; } bSelected = b; Color c = isSelected() ? LF.getLF().stdSelectedCol : Color.white; if(isFocus()) { c = Util.rgbInterpolate(c, Color.gray, .1); } setBackground(c); repaint(); statusBar.showBundles(); } } Container shutdownPanel = null; void shutdown() { if(shutdownPanel == null) { shutdownPanel = new ShutdownPanel(); cardPanel.add(shutdownPanel, "shutdown"); shutdownPanel.doLayout(); shutdownPanel.invalidate(); cardLayout.addLayoutComponent("shutdown", shutdownPanel); } cardLayout.show(cardPanel, "shutdown"); } static final int ACTION_ID_BUNDLES_ID = 0; static final int ACTION_ID_BUNDLES_NAME = 1; static final int ACTION_ID_BUNDLES_STATE = 2; static final int ACTION_ID_CONSOLE = 3; static final int ACTION_ID_OBR = 4; static final int ACTION_ID_INSTALL = 5; static final int ACTION_ID_SHUTDOWN = 6; static final int ACTION_ID_REFRESH = 7; static final int ACTION_ID_BUNDLE_START = 20; static final int ACTION_ID_BUNDLE_STOP = 21; static final int ACTION_ID_BUNDLE_UPDATE = 22; static final int ACTION_ID_BUNDLE_UNINSTALL = 23; void handleAction(int actionId) { switch(actionId) { case ACTION_ID_BUNDLES_ID: showBundles(SORT_ID); break; case ACTION_ID_BUNDLES_NAME: showBundles(SORT_NAME); break; case ACTION_ID_BUNDLES_STATE: showBundles(SORT_STATE); break; case ACTION_ID_CONSOLE: showConsole(); break; case ACTION_ID_OBR: showOBR(); break; case ACTION_ID_INSTALL: openBundle(); break; case ACTION_ID_REFRESH: refreshBundles(null); break; case ACTION_ID_SHUTDOWN: shutdown(); break; case ACTION_ID_BUNDLE_START: startBundles(); break; case ACTION_ID_BUNDLE_STOP: stopBundles(); break; case ACTION_ID_BUNDLE_UPDATE: updateBundles(); break; case ACTION_ID_BUNDLE_UNINSTALL: uninstallBundles(); break; } } class ActionMenuItem extends MenuItem implements ActionListener { int actionId; ActionMenuItem(String name, int actionId) { super(name); this.actionId = actionId; addActionListener(this); } public void actionPerformed(ActionEvent ev) { handleAction(actionId); } } class ActionImageLabel extends ImageLabel implements ActionListener { int actionId; String tt; ActionImageLabel(String name, Color bg, String tt,int actionId) { super(name, 2, bg); this.actionId = actionId; this.tt = tt; addActionListener(this); } public void actionPerformed(ActionEvent ev) { handleAction(actionId); } public void setFocus(boolean b) { super.setFocus(b); statusBar.setMessage(b ? tt : ""); } } class Toolbar extends Panel { LF lf = LF.getLF(); Toolbar() { super(new FlowLayout(FlowLayout.LEFT)); setBackground(lf.bgColor); ImageLabel viewButton = new ImageLabel("/view_select.gif", 2, getBackground()) { public void setFocus(boolean b) { super.setFocus(b); statusBar.setMessage(b ? "Select view" : ""); } }; viewPopupMenu = new PopupMenu(); add(viewPopupMenu); MenuItem item; viewPopupMenu.add(new ActionMenuItem("Bundles (id)", ACTION_ID_BUNDLES_ID)); viewPopupMenu.add(new ActionMenuItem("Bundles (name)", ACTION_ID_BUNDLES_NAME)); viewPopupMenu.add(new ActionMenuItem("Bundles (state)", ACTION_ID_BUNDLES_STATE)); viewPopupMenu.add(new ActionMenuItem("Console", ACTION_ID_CONSOLE)); viewPopupMenu.add(new ActionMenuItem("OBR (NYI)", ACTION_ID_OBR)); viewPopupMenu.add(new ActionMenuItem("Shutdown", ACTION_ID_SHUTDOWN)); viewPopupMenu.add(new ActionMenuItem("Refresh", ACTION_ID_REFRESH)); add(viewButton); viewButton.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { showPopup(e); } public void mouseReleased(MouseEvent e) { showPopup(e); } private void showPopup(MouseEvent e) { if (viewPopupMenu != null) { Component comp = e.getComponent(); viewPopupMenu.show(comp, 0, comp.getSize().height); } } }); add(new ActionImageLabel("/open.gif", getBackground(), "Install bundles", ACTION_ID_INSTALL)); add(new ActionImageLabel("/player_play.gif", getBackground(), "Start bundles", ACTION_ID_BUNDLE_START)); add(new ActionImageLabel("/player_stop.gif", getBackground(), "Stop bundles", ACTION_ID_BUNDLE_STOP)); add(new ActionImageLabel("/update.gif", getBackground(), "Update bundles", ACTION_ID_BUNDLE_UPDATE)); add(new ActionImageLabel("/player_eject.gif", getBackground(), "Uninstall bundles", ACTION_ID_BUNDLE_UNINSTALL)); } } void refreshBundles(Bundle[] bl) { ServiceReference sr = Activator.bc.getServiceReference(PackageAdmin.class.getName()); if(sr != null) { PackageAdmin packageAdmin = null; try { packageAdmin = (PackageAdmin)Activator.bc.getService(sr); if(packageAdmin != null) { if(bl != null && bl.length == 0) { bl = null; } packageAdmin.refreshPackages(bl); } } finally { if(packageAdmin != null) { Activator.bc.ungetService(sr); } } } } PopupMenu viewPopupMenu; class StatusBar extends Container { Dimension pSize = new Dimension(100, lf.defaultFont.getSize() + 4); String msg = ""; public Dimension preferredSize() { return getPreferredSize(); } public Dimension getPreferredSize() { return pSize; } public void showBundles() { int nTotal = bundles.size(); int nSelected = 0; StringBuffer sb = new StringBuffer(); for(Enumeration e = bundles.keys(); e.hasMoreElements();) { Bundle b = (Bundle)e.nextElement(); BundleC bc = (BundleC)bundles.get(b); if(bc.isSelected()) { nSelected++; if(sb.length() > 0) { sb.append(", "); } sb.append("#" + b.getBundleId() + "/" + Util.getBundleName(b)); } } if(sb.length() > 20) { sb.setLength(20); sb.append("..."); } String msg = "Total " + nTotal + ", " + nSelected + " selected" + " " + sb; setMessage(msg); } public void setMessage(String msg) { this.msg = msg; repaint(); } public void paint(Graphics g) { super.paint(g); g.setFont(lf.defaultFont); g.setColor(lf.ttText); if(msg != null) { g.drawString(msg, 2, lf.defaultFont.getSize() + 2); } g.setColor(Color.gray); } } interface Comp { public int compare(Bundle b0, Bundle b1); } Comp compName = new Comp() { public int compare(Bundle b0, Bundle b1) { String s0 = Util.getBundleName(b0).toLowerCase(); String s1 = Util.getBundleName(b1).toLowerCase(); return s0.compareTo(s1); } }; Comp compId = new Comp() { public int compare(Bundle b0, Bundle b1) { return (int)(b0.getBundleId() - b1.getBundleId()); } }; Comp compState = new Comp() { public int compare(Bundle b0, Bundle b1) { return (int)(b0.getState() - b1.getState()); } }; }