blob: 54e90769ed61999b0b9b42495b017cb8b174d50a [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.motorola.studio.android.videos.ui.views;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import com.motorola.studio.android.common.log.StudioLogger;
import com.motorola.studio.android.videos.Activator;
import com.motorola.studio.android.videos.i18n.VideosNLS;
import com.motorola.studio.android.videos.model.Video;
import com.motorola.studio.android.videos.model.VideoManager;
import com.motorola.studio.android.videos.ui.utils.UiUtilities;
/**
* A specialized Composite to be used to represent a single Video
*
*/
public class VideoComposite extends Composite
{
/*
* Video Manager
*/
private VideoManager videoManager;
/*
* The video that is being represented
*/
private Video video = null;
/*
* Resource constants
*/
private final String PLAY_ICON = "icons/play_icon.png";
private final String THUMBNAIL_LOADING_ICON = "icons/thumbnail_loading.png";
private final String THUMBNAIL_NOT_AVAILABLE_ICON = "icons/preview_not_available.png";
/*
* Other global elements and resources
*/
private Image playImg = null;
private Image thumbLoadingImg = null;
private Font videoTitleFont = null;
private Font videoTitleSelectedFont = null;
private Color highlightTextColor = null;
private Color backgroundColor = null;
private boolean showAllDescription = false;
/*
* Some widgets in the composite
*/
private StyledText videoTitle = null;
private final List<StyledText> styledTexts = new ArrayList<StyledText>();
/*
* Parent class
*/
private VideosListComposite parentClass = null;
private final ScrolledComposite scrollParent;
/*
* Layout details
*/
private final int MINIMUM_DESCRIPTION_COLUMN_WIDTH = 200;
/**
* Constructor responsible for creating the entire component
*
* @param parent the parent composite
* @param style SWT style
* @param video the video to be represented
*/
public VideoComposite(VideosListComposite parentClass, Composite parent,
ScrolledComposite scrollParent, int style, Video video)
{
super(parent, style);
this.video = video;
this.parentClass = parentClass;
this.scrollParent = scrollParent;
init();
createControls();
}
/**
* Initialize variables and resources
*/
private void init()
{
try
{
// Video Manager instance
videoManager = VideoManager.getInstance();
/*
* Images to be used
*/
playImg =
new Image(getShell().getDisplay(), FileLocator.toFileURL(
Activator.getDefault().getBundle().getEntry(PLAY_ICON)).getPath());
thumbLoadingImg =
new Image(getShell().getDisplay(), FileLocator.toFileURL(
Activator.getDefault().getBundle().getEntry(THUMBNAIL_LOADING_ICON))
.getPath());
/*
* Fonts
*/
videoTitleFont =
new Font(getShell().getDisplay(), getShell().getDisplay().getSystemFont()
.getFontData()[0].getName(), 10, SWT.BOLD);
videoTitleSelectedFont =
new Font(getShell().getDisplay(), getShell().getDisplay().getSystemFont()
.getFontData()[0].getName(), 10, SWT.BOLD | SWT.ITALIC);
/*
* Colors
*/
backgroundColor = getShell().getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
highlightTextColor = getShell().getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);
}
catch (Exception e)
{
StudioLogger.error(this.getClass(), "Error while initializing Video Composite", e);
}
}
/**
* Create all widgets of this composite
*/
private void createControls()
{
// set the composite layout
setLayout(new GridLayout(3, false));
setBackground(backgroundColor);
// Set loading thumbnail image
final Label videoImage = new Label(this, SWT.NONE);
videoImage.setImage(thumbLoadingImg);
// Get the real thumbnail
Thread updateVideoImage = new Thread(new Runnable()
{
public void run()
{
// this operation is time consuming (require internet access)
// that's why we are using a new thread and just after we have the
// file download we use the UI thread
final File thumbnail = videoManager.getThumbnail(video.getSnapshot());
Display.getDefault().syncExec(new Runnable()
{
public void run()
{
Image videoImg =
thumbnail != null ? new Image(getShell().getDisplay(), thumbnail
.toString()) : null;
// make sure the element still exists, the view can be closed
if (!videoImage.isDisposed())
{
if (videoImg != null)
{
videoImage.setImage(videoImg);
}
else
{
ImageData notAvailable =
Activator.imageDescriptorFromPlugin(Activator.PLUGIN_ID,
THUMBNAIL_NOT_AVAILABLE_ICON).getImageData();
Point size = videoImage.getSize();
if (videoImage.getImage() != null
&& !videoImage.getImage().isDisposed())
{
size =
new Point(videoImage.getImage().getBounds().width,
videoImage.getImage().getBounds().height);
videoImage.getImage().dispose();
}
videoImage.setImage(new Image(getShell().getDisplay(), notAvailable
.scaledTo(size.x, size.y)));
}
}
}
});
}
});
updateVideoImage.start();
videoImage.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
videoImage.setBackground(backgroundColor);
final Composite titleAndDescriptionComposite =
new Composite(this, SWT.WRAP | SWT.BACKGROUND);
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
data.widthHint = MINIMUM_DESCRIPTION_COLUMN_WIDTH;
data.minimumWidth = MINIMUM_DESCRIPTION_COLUMN_WIDTH;
data.heightHint = videoImage.getSize().y;
titleAndDescriptionComposite.setLayoutData(data);
titleAndDescriptionComposite.setLayout(new GridLayout(1, true));
titleAndDescriptionComposite.setBackground(backgroundColor);
videoTitle = new StyledText(titleAndDescriptionComposite, SWT.WRAP | SWT.BACKGROUND);
videoTitle.setEnabled(false);
videoTitle.setBackground(backgroundColor);
videoTitle.setFont(videoTitleFont);
data = new GridData(SWT.FILL, SWT.FILL, true, false);
videoTitle.setLayoutData(data);
styledTexts.add(videoTitle);
final StyledText videoDescription =
new StyledText(titleAndDescriptionComposite, SWT.WRAP | SWT.BACKGROUND);
videoDescription.setEnabled(false);
videoDescription.setBackground(backgroundColor);
data = new GridData(SWT.FILL, SWT.FILL, true, true);
videoDescription.setLayoutData(data);
styledTexts.add(videoDescription);
Composite playButtonArea = new Composite(this, SWT.NONE);
GridLayout layout = new GridLayout(1, true);
playButtonArea.setLayoutData(new GridData(SWT.NONE, SWT.NONE, false, false));
playButtonArea.setLayout(layout);
playButtonArea.setBackground(backgroundColor);
Label playImage = new Label(playButtonArea, SWT.NONE);
playImage.setImage(playImg);
playImage.setBackground(backgroundColor);
playImage.setToolTipText(VideosNLS.UI_Play_Video);
playImage.setCursor(new Cursor(getShell().getDisplay(), SWT.CURSOR_HAND));
playImage.setLayoutData(new GridData(SWT.NONE, SWT.NONE, false, false));
videoTitle.setText(video.getTitle());
videoDescription.setText(video.getDescription());
final Label moreText = new Label(playButtonArea, SWT.WRAP | SWT.BACKGROUND);
moreText.addMouseListener(new MouseListener()
{
public void mouseUp(MouseEvent e)
{
if (!showAllDescription)
{
showAllDescription = true;
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
data.widthHint = MINIMUM_DESCRIPTION_COLUMN_WIDTH;
data.minimumWidth = MINIMUM_DESCRIPTION_COLUMN_WIDTH;
titleAndDescriptionComposite.setLayoutData(data);
}
else
{
showAllDescription = false;
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
data.widthHint = MINIMUM_DESCRIPTION_COLUMN_WIDTH;
data.minimumWidth = MINIMUM_DESCRIPTION_COLUMN_WIDTH;
data.heightHint = videoImage.getSize().y;
titleAndDescriptionComposite.setLayoutData(data);
}
// redraw everything
parentClass.layout();
((Composite) scrollParent.getContent()).layout(true);
scrollParent.setMinSize(scrollParent.getContent().computeSize(SWT.DEFAULT,
SWT.DEFAULT));
}
public void mouseDown(MouseEvent e)
{
//do nothing
}
public void mouseDoubleClick(MouseEvent e)
{
//do nothing
}
});
titleAndDescriptionComposite.addControlListener(new ControlListener()
{
public void controlResized(ControlEvent e)
{
Point descriptionPreferedSize =
videoDescription.computeSize(titleAndDescriptionComposite.getSize().x,
SWT.DEFAULT);
Point titlePreferedSize =
videoTitle.computeSize(titleAndDescriptionComposite.getSize().x,
SWT.DEFAULT);
int preferedHeight = descriptionPreferedSize.y + titlePreferedSize.y;
if (preferedHeight + 20 > videoImage.getSize().y)
{
moreText.setCursor(new Cursor(getShell().getDisplay(), SWT.CURSOR_HAND));
moreText.setBackground(backgroundColor);
GridData data = new GridData(SWT.CENTER, SWT.TOP, false, false);
moreText.setLayoutData(data);
moreText.setVisible(true);
if (!showAllDescription)
{
moreText.setText("(+)");
moreText.setToolTipText(VideosNLS.UI_More);
}
else
{
moreText.setText("(-)");
moreText.setToolTipText(VideosNLS.UI_Less);
}
}
else
{
moreText.setVisible(false);
moreText.setCursor(new Cursor(getShell().getDisplay(), SWT.CURSOR_ARROW));
}
}
public void controlMoved(ControlEvent e)
{
// do nothing
}
});
playImage.addMouseListener(new MouseAdapter()
{
@Override
public void mouseDown(MouseEvent e)
{
Event event = new Event();
event.data = video;
parentClass.notifyListeners(MOTODEVVideosView.PLAY_LISTENER, event);
}
});
// create and set the pop-up menu for the composite and all widgets in the composite
setMenuForAllWidgets(this, createVideoPopupMenu());
}
/**
* Add a menu item in the video composite right-click, with options
* to copy the video URL
*
* @param videoComposite the video composite
* @param video the video being represented by the composite
* @return the menu
*/
private Menu createVideoPopupMenu()
{
Menu popupMenu = new Menu(getShell(), SWT.POP_UP);
MenuItem videoUrl = new MenuItem(popupMenu, SWT.NONE);
videoUrl.setText(VideosNLS.UI_Copy_URL);
MenuItem videoEmbeddedUrl = new MenuItem(popupMenu, SWT.NONE);
videoEmbeddedUrl.setText(VideosNLS.UI_Copy_Embedded_URL);
videoUrl.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
copyTextToClipboard(video.getExternalLink());
}
});
videoEmbeddedUrl.addSelectionListener(new SelectionAdapter()
{
@Override
public void widgetSelected(SelectionEvent e)
{
copyTextToClipboard(video.getEmbeddedLink());
}
});
return popupMenu;
}
/**
* Recursively add the menu for all widgets
*
* @param mainComposite the main composite
* @param popupMenu the menu to be added to the main composite all all children widgets
*/
private void setMenuForAllWidgets(Composite mainComposite, Menu popupMenu)
{
mainComposite.setMenu(popupMenu);
for (Control control : mainComposite.getChildren())
{
control.setMenu(popupMenu);
if (control instanceof Composite && ((Composite) control).getChildren().length > 0)
{
setMenuForAllWidgets((Composite) control, popupMenu);
}
}
}
/**
* Copy the selected text to clipboard
*
* @param text the text to be copied to the clipboard
*/
private void copyTextToClipboard(String text)
{
Clipboard clipboard = new Clipboard(getShell().getDisplay());
clipboard.setContents(new Object[]
{
text
}, new Transfer[]
{
TextTransfer.getInstance()
});
}
/**
* Change the element appearance to mark it as selected
*/
public void select()
{
videoTitle.setFont(videoTitleSelectedFont);
}
/**
* Change the element appearance to the default one
*/
public void deselect()
{
videoTitle.setFont(videoTitleFont);
}
/**
* Highlight the given keyword in the composite
*
* @param keyword the keyword to be highlighted
*/
public void highlightKeyword(String keyword)
{
for (StyledText styledText : styledTexts)
{
UiUtilities.highlightKeywords(styledText, keyword, highlightTextColor);
}
}
/**
* Retrieve the video being represented
*
* @return the video that is being represented
*/
public Video getVideo()
{
return video;
}
}