Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorderable cards #129

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 161 additions & 3 deletions src/main/java/bdv/ui/CardPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand All @@ -55,6 +56,7 @@
import javax.swing.JToggleButton;
import javax.swing.Scrollable;
import javax.swing.border.EmptyBorder;

import net.miginfocom.swing.MigLayout;

/**
Expand All @@ -72,6 +74,8 @@ public class CardPanel

private final static Color DEFAULT_HEADER_BACKGROUND = new Color( 0xcccccc );

private final static Color DEFAULT_HEADER_HIGHLIGHTED_BACKGROUND = new Color( 0xddccbb );

private final static Color DEFAULT_HEADER_FOREGROUND = new Color( 0x202020 );

private Color headerBackground = DEFAULT_HEADER_BACKGROUND;
Expand All @@ -84,13 +88,16 @@ public class CardPanel

private final Container container;

private ReorderMouseHandler reorderHandler;

/**
* Empty card panel.
*/
public CardPanel()
{
container = new Container( new MigLayout( "fillx, ins 0", "[grow]", "[]0[]" ) );
container.setBackground( DEFAULT_CARD_BACKGROUND );
reorderHandler = new ReorderMouseHandler( this );
}

public JComponent getComponent()
Expand Down Expand Up @@ -164,6 +171,64 @@ public boolean addCard( final Object key, final String title, final JComponent c
return addCard( key, title, component, expanded, null );
}

public static <T> void move( List<T> list, int from, int to )
{
final ArrayList<T> reorderedList = new ArrayList<T>();

/*
* If container and card list are allowed to store
* cards in different order, it could save a little work here,
* though the permutation between the two would probably need to be stored.
*/

// reorder
int j = 0;
for( int i = 0; i < list.size(); i++ ) {
if( i == to )
reorderedList.add(list.get( from ));
else if( j == from)
{
j++;
reorderedList.add(list.get( j++ ));
}
else
reorderedList.add(list.get( j++ ));
}

list.removeIf(x -> true);
list.addAll(reorderedList);
}

public synchronized void moveCard( Card src, Card dst )
{
moveCard(cardList.indexOf(src), cardList.indexOf(dst));
}

public synchronized void moveCard( int from, int to )
{
/*
* If container and card list are allowed to store
* cards in different order, it could save a little work here,
* though the permutation between the two would probably need to be stored.
*/
move( cardList, from, to );
container.removeAll();
for( Card card : cardList )
container.add( card, "growx, wrap" );

container.revalidate();
}

public synchronized void swapCards( int from, int to )
{
Collections.swap(cardList, from, to);
container.removeAll();
for( Card card : cardList )
container.add( card, "growx, wrap" );

container.revalidate();
}

/**
* Remove a card. If the card does not exist, nothing happens.
*
Expand Down Expand Up @@ -344,7 +409,7 @@ public Card( final Object key, final String title, final JComponent component, f
terminalResizePanel = new TerminalResizePanel( componentPanel );
terminalResizePanel.setBackground( getHeaderBackground() );

headerPanel = new HeaderPanel( title );
headerPanel = new HeaderPanel( title, this );
headerPanel.setBackground( getHeaderBackground() );
headerPanel.setForeground( getHeaderForeground() );

Expand All @@ -354,12 +419,29 @@ public Card( final Object key, final String title, final JComponent component, f
this.setExpanded( open );
}

private class HeaderPanel extends JPanel
private class HeaderPanel extends JPanel implements DraggableHeader
{
private final JPanel labelPanel;

private final JLabel label;

private final Card parentCard;

public Card getParent()
{
return parentCard;
}

public void enterAction()
{
labelPanel.setBackground(DEFAULT_HEADER_HIGHLIGHTED_BACKGROUND);
}

public void exitAction()
{
labelPanel.setBackground(DEFAULT_HEADER_BACKGROUND);
}

@Override
public void setBackground( final Color bg )
{
Expand All @@ -376,10 +458,11 @@ public void setForeground( final Color fg )
label.setForeground( fg );
}

public HeaderPanel( final String title )
public HeaderPanel( final String title, Card parentCard )
{
super( new MigLayout( "fillx, aligny center, ins 0 0 0 0", "[][grow]", "" ) );
UIUtils.setPreferredWidth( this, 100 );
this.parentCard = parentCard;

// Holds the name with insets.
labelPanel = new JPanel( new MigLayout( "fillx, ins 0 4 0 4", "[grow]", "" ) );
Expand Down Expand Up @@ -428,9 +511,13 @@ public JComponent getComponent()
return getContentOfCardAbove();
}
} );

addMouseListener( resizeHandler );
addMouseMotionListener( resizeHandler );

addMouseListener( reorderHandler );
addMouseMotionListener( reorderHandler );

add( collapseButton );
add( labelPanel, "growx" );
}
Expand Down Expand Up @@ -577,6 +664,77 @@ public void mouseDragged( final MouseEvent e )
}
}

private interface DraggableHeader{
public Card getParent();
public void enterAction();
public void exitAction();
}

private static class ReorderMouseHandler extends MouseAdapter
{
private CardPanel cardPanel;

private DraggableHeader srcHeader;

private Card srcCard;

private Card dstCard;

public ReorderMouseHandler( final CardPanel cardPanel )
{
this.cardPanel = cardPanel;
}

@Override
public void mousePressed( final MouseEvent e )
{
final Component comp = e.getComponent();
if( comp instanceof DraggableHeader )
{
DraggableHeader headerPanel = (DraggableHeader)comp;
srcCard = headerPanel.getParent();
srcHeader = headerPanel;
}
}

@Override
public void mouseReleased( final MouseEvent e )
{
srcCard = null;
dstCard = null;
srcHeader = null;
}

@Override
public void mouseEntered( final MouseEvent e )
{
final Component comp = e.getComponent();
if( comp instanceof DraggableHeader )
{
DraggableHeader headerPanel = (DraggableHeader)comp;
if( srcCard != null)
{
dstCard = headerPanel.getParent();
cardPanel.moveCard( srcCard, dstCard );
}
else
headerPanel.enterAction();
}
}

@Override
public void mouseExited( final MouseEvent e )
{
final Component comp = e.getComponent();
if( comp instanceof DraggableHeader )
{
DraggableHeader headerPanel = (DraggableHeader)comp;
if( headerPanel != srcHeader )
headerPanel.exitAction();
}
}
}

// =================================================================

/**
Expand Down