/**
*
* Copyright
* 2009-2015 Jayway Products AB
* 2016-2017 Föreningen Sambruk
*
* Licensed under AGPL, Version 3.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.gnu.org/licenses/agpl.txt
*
* 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 se.streamsource.streamflow.client.util;
import ca.odell.glazedlists.SeparatorList;
import ca.odell.glazedlists.swing.EventListModel;
import com.jgoodies.forms.factories.Borders;
import se.streamsource.dci.value.link.LinkValue;
import se.streamsource.dci.value.link.TitledLinkValue;
import se.streamsource.streamflow.client.ui.OptionsAction;
import se.streamsource.streamflow.infrastructure.event.domain.TransactionDomainEvents;
import se.streamsource.streamflow.infrastructure.event.domain.source.TransactionListener;
import se.streamsource.streamflow.infrastructure.event.domain.source.helper.Events;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.BorderLayout;
import java.awt.Component;
/**
* JAVADOC
*/
public abstract class ListDetailView
extends JSplitPane
implements TransactionListener
{
protected JList list;
public ListDetailView()
{
setBorder( Borders.createEmptyBorder("2dlu, 2dlu, 2dlu, 2dlu"));
setRightComponent( new JPanel() );
setBorder( BorderFactory.createEmptyBorder() );
setDividerLocation( 250 );
setOneTouchExpandable( true );
}
protected void initMaster( EventListModel<LinkValue> listModel, Action createAction, Action[] selectionActions, final DetailFactory factory, ListCellRenderer renderer )
{
initMaster( listModel, createAction, new SelectionActionEnabler( selectionActions ), false, factory, renderer );
}
protected void initMaster( EventListModel<LinkValue> listModel, Action createAction, Action[] selectionActions, final DetailFactory factory)
{
initMaster( listModel, createAction, selectionActions, false, factory);
}
protected void initMaster( EventListModel<LinkValue> listModel, Action createAction, SelectionActionEnabler selectionActionEnabler, final DetailFactory factory)
{
initMaster( listModel, createAction, selectionActionEnabler, false, factory);
}
protected void initMaster( EventListModel<LinkValue> listModel, Action createAction, Action[] selectionActions, boolean actionsWithoutOption, final DetailFactory factory)
{
initMaster( listModel, createAction, new SelectionActionEnabler( selectionActions ), actionsWithoutOption, factory, new LinkListCellRenderer() );
}
protected void initMaster( EventListModel<LinkValue> listModel, Action createAction, SelectionActionEnabler selectionActionEnabler, boolean actionsWithoutOption, final DetailFactory factory)
{
initMaster( listModel, createAction, selectionActionEnabler, actionsWithoutOption, factory, new LinkListCellRenderer() );
}
protected void initMaster( EventListModel<LinkValue> listModel, Action createAction, SelectionActionEnabler selectionActionEnabler, final DetailFactory factory, ListCellRenderer renderer )
{
initMaster( listModel, createAction,selectionActionEnabler, false, factory, renderer );
}
protected void initMaster( EventListModel<TitledLinkValue> listModel, final DetailFactory factory )
{
initMaster( listModel, null,new SelectionActionEnabler(new Action[]{}),false,factory, new SeparatorListCellRenderer( new LinkListCellRenderer() ));
}
/**
* This method creates and regulates a master detail.
* This method contains a workaround for the streamflow client server action concept. ResourceModels are telling what kind of resources and commands or querys are available
* on the server. Client code should use ResourceActionEnabler, SelectionActionEnabler, RefreshComponents classes to steer what actions become enabled or not.
* This is right now not honored completely throughout the administration gui - especially for option actions. They are for the most views enabled by default if a selection in
* a list is made. For the time being we will have to work around occasions where option actions need to be steered from server side, hence the usage of SelectionActionEnabler as
* method parameter. That makes it possible to send in a custom selection enabler. See @se.streamsource.streamflow.client.ui.administration.users.initMaster()
* @param listModel
* @param createAction
* @param selectionActionEnabler The selection action enabler to use
* @param actionsWithoutOption
* @param factory
* @param renderer
*/
protected void initMaster( EventListModel<? extends LinkValue> listModel, Action createAction, SelectionActionEnabler selectionActionEnabler, boolean actionsWithoutOption, final DetailFactory factory, ListCellRenderer renderer)
{
list = new JList(listModel);
list.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
list.setCellRenderer( renderer );
JScrollPane scrollPane = new JScrollPane( list );
JPanel master = new JPanel(new BorderLayout());
master.add( scrollPane, BorderLayout.CENTER );
// Toolbar
JPanel toolbar = new JPanel();
if (createAction != null)
toolbar.add( new StreamflowButton( createAction ) );
list.getSelectionModel().addListSelectionListener( selectionActionEnabler );
if( actionsWithoutOption)
{
for (Action selectionAction : selectionActionEnabler.getActions())
{
toolbar.add( new StreamflowButton( selectionAction ) );
}
} else
{
if (selectionActionEnabler.getActions().length != 0)
{
JPopupMenu options = new JPopupMenu();
for (Action selectionAction : selectionActionEnabler.getActions())
{
options.add( selectionAction );
}
toolbar.add( new StreamflowButton( new OptionsAction( options ) ) );
}
}
master.add( toolbar, BorderLayout.SOUTH);
setLeftComponent( master );
list.addListSelectionListener( new ListSelectionListener()
{
public void valueChanged( ListSelectionEvent e )
{
if (!e.getValueIsAdjusting() )
{
if(!(list.getSelectedValue() instanceof SeparatorList.Separator))
{
LinkValue detailLink = (LinkValue) list.getSelectedValue();
if (detailLink != null)
{
int selectedIndex = -1;
if (getRightComponent() != null && getRightComponent() instanceof TabbedResourceView)
{
TabbedResourceView tab = (TabbedResourceView) getRightComponent();
// selectedIndex = tab.getSelectedIndex();
}
Component detailView = factory.createDetail( detailLink );
if (detailView instanceof TabbedResourceView)
{
// ((TabbedResourceView)detailView).setSelectedIndex( selectedIndex );
}
setRightComponent( detailView );
if (detailView instanceof ListDetailView || detailView instanceof TabbedResourceView)
{
ListDetailView parentListDetailView = (ListDetailView) SwingUtilities.getAncestorOfClass( ListDetailView.class, ListDetailView.this);
if (parentListDetailView != null)
parentListDetailView.setDividerLocation( 0 );
}
} else
{
setRightComponent( new JPanel() );
}
}
}
}
} );
}
public interface DetailFactory
{
Component createDetail(LinkValue detailLink);
}
protected LinkValue getSelectedValue()
{
return (LinkValue) list.getSelectedValue();
}
public void notifyTransactions( Iterable<TransactionDomainEvents> transactions )
{
if (Events.matches(Events.withUsecases( "delete", "move" ), transactions)
&& !Events.matches( Events.withNames( /*"removedLabel",*/ "removedSelectedForm", "removedParticipant"), transactions ))
list.clearSelection();
}
}