/*******************************************************************************
* Copyright (c) 2011 Bug Labs, Inc.
* 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 Bug Labs, Inc. 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 com.buglabs.bug.appui;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Image;
import java.awt.Label;
import java.awt.PopupMenu;
import java.awt.event.MouseListener;
import java.net.URL;
import java.util.Map;
import org.osgi.framework.Bundle;
import com.buglabs.util.ui.IDesktopApp;
/**
* This AWT container represents icon and text for an app.
* @author kgilmer
*
*/
public class AppWidget extends Container {
private static final int ICON_SIZE_Y = 32;
private static final int ICON_SIZE_X = ICON_SIZE_Y;
private static final long serialVersionUID = -2570755730671986150L;
private static final int FONT_HEIGHT = 12;
//TODO determine real screen depth
private static final int SCREEN_DEPTH = 8;
/**
* Max number of characters an app name can be before truncation.
*/
private static final int MAX_NAME_LENGTH = 9;
private static final String TRUNCATE_STRING = "..";
private static final Dimension WIDGET_SIZE = new Dimension(64, 44);
private final PopupMenu menu = new PopupMenu();
private final IDesktopApp desktopApp;
private final String appName;
/**
* @param name name of icon
* @param launchListeners listeners
* @param bundle bundle
* @param font font
*/
public AppWidget(final String name, final Map<String, IDesktopApp> launchListeners, Bundle bundle, Font font) {
appName = name;
desktopApp = (IDesktopApp) launchListeners.get(name);
AppIcon icon = new AppIcon(getIcon(desktopApp, bundle), Activator.APP_INVERTED);
MouseListener listener = new AppIconMouseListener(icon, desktopApp, menu);
this.addMouseListener(listener);
icon.setSize(ICON_SIZE_X, ICON_SIZE_Y);
icon.setBounds((ICON_SIZE_X / 2), 0, ICON_SIZE_X, ICON_SIZE_Y);
final Label label = new Label(formatName(name));
label.setFont(font);
label.setAlignment(Label.CENTER);
label.setBounds(0, ICON_SIZE_Y + 2, ICON_SIZE_X * 2, FONT_HEIGHT);
populateMenu(menu, desktopApp, bundle.getState());
menu.addActionListener(new AppActionListener(desktopApp, bundle, Activator.getLogService()));
add(icon);
add(menu);
add(label);
}
/**
* Load the icon image for the app.
*
* @param app The application
* @param bundle The bundle representing the application
* @return Icon as image
*/
private Image getIcon(IDesktopApp app, Bundle bundle) {
//Custom icon provided by app.
if (app != null) {
URL imageFile = app.getIcon(ICON_SIZE_Y, ICON_SIZE_Y, SCREEN_DEPTH);
if (imageFile != null) {
return Activator.AWT_TOOLKIT.createImage(imageFile);
}
}
//default app icon for IDesktopApp clients
if (app != null) {
return Activator.APP_ACTIVE;
}
//A running app bundle that isn't a IDesktopApp
if (bundle.getState() == Bundle.ACTIVE) {
return Activator.BUNDLE_STARTED;
}
//A non-running bundle.
return Activator.BUNDLE_STOPPED;
}
/**
* Populate the menu.
*
* @param m menu
* @param app application
* @param state bundle state
*/
private void populateMenu(PopupMenu m, IDesktopApp app, int state) {
//Display app title.
m.add(appName);
m.getItem(m.getItemCount() - 1).setEnabled(false);
m.addSeparator();
//If app contributes a menu, add it.
if (app != null) {
String[] items = app.getMenuItems();
if (items != null && items.length > 0) {
for (int i = 0; i < items.length; ++i) {
m.add(items[i]);
}
m.addSeparator();
}
}
m.add(AppActionListener.ACTION_BUNDLE_START);
m.getItem(m.getItemCount() - 1).setEnabled(state != Bundle.ACTIVE);
m.add(AppActionListener.ACTION_BUNDLE_STOP);
m.getItem(m.getItemCount() - 1).setEnabled(state == Bundle.ACTIVE);
m.addSeparator();
m.add(AppActionListener.ACTION_BUNDLE_UNINSTALL);
}
/**
* Truncate bundle name if necessary.
*
* @param name String to be formatted.
* @return The input string truncated if exceeds maximum length defined in MAX_NAME_LENGTH.
*/
private String formatName(String name) {
if (name.length() < MAX_NAME_LENGTH) {
return name;
}
return name.substring(0, MAX_NAME_LENGTH - (TRUNCATE_STRING.length())) + TRUNCATE_STRING;
}
/* (non-Javadoc)
* @see java.awt.Container#getPreferredSize()
*/
public Dimension getPreferredSize() {
return WIDGET_SIZE;
}
/* (non-Javadoc)
* @see java.awt.Container#getMinimumSize()
*/
public Dimension getMinimumSize() {
return WIDGET_SIZE;
}
}