package org.limewire.ui.swing.search.advanced;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import net.miginfocom.swing.MigLayout;
import org.jdesktop.application.Resource;
import org.jdesktop.swingx.JXButton;
import org.jdesktop.swingx.JXPanel;
import org.limewire.core.api.Category;
import org.limewire.core.api.FilePropertyKey;
import org.limewire.core.api.library.FriendAutoCompleterFactory;
import org.limewire.core.api.properties.PropertyDictionary;
import org.limewire.core.api.search.SearchCategory;
import org.limewire.ui.swing.action.AbstractAction;
import org.limewire.ui.swing.components.Disposable;
import org.limewire.ui.swing.components.HeaderBar;
import org.limewire.ui.swing.components.decorators.ButtonDecorator;
import org.limewire.ui.swing.components.decorators.HeaderBarDecorator;
import org.limewire.ui.swing.search.KeywordAssistedSearchBuilder;
import org.limewire.ui.swing.search.SearchInfo;
import org.limewire.ui.swing.search.UiSearchListener;
import org.limewire.ui.swing.util.FontUtils;
import org.limewire.ui.swing.util.GuiUtils;
import org.limewire.ui.swing.util.I18n;
import org.limewire.ui.swing.util.ResizeUtils;
import com.google.inject.Inject;
import com.google.inject.Provider;
/** The container for advanced searching. */
public class AdvancedSearchPanel extends JXPanel implements Disposable {
private final FriendAutoCompleterFactory friendAutoCompleterFactory;
private final Provider<KeywordAssistedSearchBuilder> advancedSearchBuilder;
private final PropertyDictionary propertyDictionary;
private final ButtonDecorator buttonDecorator;
private final Action searchAction = new SearchAction();
/* CoW so that listeners can modify the list of listeners. */
private final List<UiSearchListener> uiSearchListeners = new CopyOnWriteArrayList<UiSearchListener>();
private Map<Category, AdvancedPanel> advancedPanels = new HashMap<Category, AdvancedPanel>();
private AdvancedPanel visibleComponent = null;
private final JPanel selectorPanel;
private final JPanel inputPanel;
@Resource private Font headingFont;
private final JXButton searchButton = new JXButton(searchAction);
@Inject
public AdvancedSearchPanel(PropertyDictionary propertyDictionary, FriendAutoCompleterFactory friendAutoCompleterFactory,
HeaderBarDecorator headerDecorator, ButtonDecorator buttonDecorator, Provider<KeywordAssistedSearchBuilder> advancedSearchBuilder) {
this.propertyDictionary = propertyDictionary;
this.friendAutoCompleterFactory = friendAutoCompleterFactory;
this.buttonDecorator = buttonDecorator;
this.advancedSearchBuilder = advancedSearchBuilder;
GuiUtils.assignResources(this);
setLayout(new MigLayout("insets 0, gap 0, hidemode 3"));
HeaderBar heading = new HeaderBar(I18n.tr("Advanced Search"));
headerDecorator.decorateBasic(heading);
JLabel description = new JLabel(I18n.tr("Search for the following category:"));
description.setFont(headingFont);
add(heading, "dock north");
add(description, "gapleft 15, gaptop 15, wrap");
selectorPanel = new JPanel(new FlowLayout());
selectorPanel.setOpaque(false);
add(selectorPanel, "gapleft 30, gaptop 5, wrap");
inputPanel = new JPanel(new MigLayout("insets 0, gap 0, hidemode 3, wrap"));
addCategory(SearchCategory.AUDIO);
addCategory(SearchCategory.VIDEO);
addCategory(SearchCategory.IMAGE);
addCategory(SearchCategory.DOCUMENT);
addCategory(SearchCategory.PROGRAM);
buttonDecorator.decorateGreenFullButton(searchButton);
searchButton.setFont(headingFont);
searchButton.setVisible(false);
JPanel searchButtonPanel = new JPanel(new MigLayout("insets 0, gap 0, fill"));
searchButtonPanel.add(searchButton, "dock east");
inputPanel.add(searchButtonPanel, "dock south, gapbefore push, gapright 5, gaptop 5");
add(inputPanel, "gapleft 45, gaptop 4");
}
/**
* Creates the correct AdvancedPanel based on the category
* selected.
*/
private AdvancedPanel createAdvancedPanel(Category category) {
Action enterKeyAction = new AbstractAction("pressed") {
public void actionPerformed(ActionEvent e) {
searchButton.doClick();
}
};
AdvancedPanel panel = null;
if(category == Category.AUDIO) {
panel = new AdvancedAudioPanel(propertyDictionary, friendAutoCompleterFactory, enterKeyAction);
} else if(category == Category.VIDEO) {
panel = new AdvancedVideoPanel(propertyDictionary, friendAutoCompleterFactory, enterKeyAction);
} else if(category == Category.DOCUMENT) {
panel = new AdvancedDocumentPanel(friendAutoCompleterFactory, enterKeyAction);
} else if(category == Category.IMAGE) {
panel = new AdvancedImagePanel(friendAutoCompleterFactory, enterKeyAction);
} else if(category == Category.PROGRAM) {
panel = new AdvancedProgramPanel(friendAutoCompleterFactory, enterKeyAction);
}
return panel;
}
private void addCategory(final SearchCategory category) {
final JXButton button = new JXButton(I18n.tr(category.getCategory().getPluralName()));
button.setModel(new JToggleButton.ToggleButtonModel());
buttonDecorator.decorateLinkButton(button);
button.setFont(headingFont);
FontUtils.underline(button);
selectorPanel.add(button);
button.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent event) {
if (event.getStateChange() == ItemEvent.SELECTED) {
AdvancedPanel component = advancedPanels.get(category.getCategory());
if(component == null) {
component = createAdvancedPanel(category.getCategory());
advancedPanels.put(category.getCategory(), component);
ResizeUtils.forceWidth(component, 300);
inputPanel.add(component);
}
// Update visibility so invisible panels don't effect size
if (visibleComponent != null) {
visibleComponent.setVisible(false);
}
component.setVisible(true);
visibleComponent = component;
updateSelection(button);
searchButton.setVisible(true);
}
}
});
}
private void updateSelection(JButton button) {
button.setSelected(true);
for ( Component comp : selectorPanel.getComponents() ) {
if (comp instanceof JButton && button != comp) {
((JButton)comp).setSelected(false);
}
}
}
/** Adds a listener that will be notified when an advanced search is triggered. */
public void addSearchListener(UiSearchListener uiSearchListener) {
uiSearchListeners.add(uiSearchListener);
}
/**
* Action that creates a search and notifies all listeners.
*/
private class SearchAction extends AbstractAction {
public SearchAction() {
super(I18n.tr("Search"));
}
@Override
public void actionPerformed(ActionEvent e) {
if(visibleComponent != null) {
Map<FilePropertyKey,String> searchData = visibleComponent.getSearchData();
if(searchData != null) {
SearchInfo info = advancedSearchBuilder.get().createAdvancedSearch(searchData,
visibleComponent.getSearchCategory());
for(UiSearchListener uiSearchListener : uiSearchListeners) {
uiSearchListener.searchTriggered(info);
}
}
}
}
}
@Override
public void dispose() {
uiSearchListeners.clear();
}
}