John Crygier
2012-05-07 0e6eace75d39ef300891b529d471617b5da8cfaa
Add custom fields to the manager
1 files added
2 files modified
543 ■■■■■ changed files
src/com/gitblit/client/EditRepositoryDialog.java 45 ●●●●● patch | view | raw | blame | history
src/com/gitblit/client/RepositoriesPanel.java 2 ●●●●● patch | view | raw | blame | history
src/com/gitblit/client/VerticalFlowLayout.java 496 ●●●●● patch | view | raw | blame | history
src/com/gitblit/client/EditRepositoryDialog.java
@@ -28,6 +28,7 @@
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -44,10 +45,12 @@
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.ListCellRenderer;
import javax.swing.ScrollPaneConstants;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.FederationStrategy;
@@ -117,6 +120,8 @@
    private JLabel postReceiveInherited;
    private Set<String> repositoryNames;
    private JPanel customFieldsPanel;
    public EditRepositoryDialog(int protocolVersion) {
        this(protocolVersion, new RepositoryModel());
@@ -277,6 +282,11 @@
        JPanel postReceivePanel = new JPanel(new BorderLayout(5, 5));
        postReceivePanel.add(postReceivePalette, BorderLayout.CENTER);
        postReceivePanel.add(postReceiveInherited, BorderLayout.WEST);
        customFieldsPanel = new JPanel(new VerticalFlowLayout());
        JScrollPane customFieldsScrollPane = new JScrollPane(customFieldsPanel);
        customFieldsScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        customFieldsScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
        JTabbedPane panel = new JTabbedPane(JTabbedPane.TOP);
        panel.addTab(Translation.get("gb.general"), fieldsPanel);
@@ -290,6 +300,9 @@
        }
        panel.addTab(Translation.get("gb.preReceiveScripts"), preReceivePanel);
        panel.addTab(Translation.get("gb.postReceiveScripts"), postReceivePanel);
        panel.addTab(Translation.get("gb.customFields"), customFieldsScrollPane);
        JButton createButton = new JButton(Translation.get("gb.save"));
        createButton.addActionListener(new ActionListener() {
@@ -331,11 +344,15 @@
        pack();
        nameField.requestFocus();
    }
    private JPanel newFieldPanel(String label, JComponent comp) {
        return newFieldPanel(label, 150, comp);
    }
    private JPanel newFieldPanel(String label, int labelSize, JComponent comp) {
        JLabel fieldLabel = new JLabel(label);
        fieldLabel.setFont(fieldLabel.getFont().deriveFont(Font.BOLD));
        fieldLabel.setPreferredSize(new Dimension(150, 20));
        fieldLabel.setPreferredSize(new Dimension(labelSize, 20));
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0));
        panel.add(fieldLabel);
        panel.add(comp);
@@ -448,6 +465,15 @@
        repository.indexedBranches = indexedBranchesPalette.getSelections();
        repository.preReceiveScripts = preReceivePalette.getSelections();
        repository.postReceiveScripts = postReceivePalette.getSelections();
        // Custom Fields
        repository.customFields = new HashMap<String, String>();
        for (Component aCustomFieldPanel : customFieldsPanel.getComponents()) {
            JTextField textField = (JTextField) ((JPanel)aCustomFieldPanel).getComponent(1);
            repository.customFields.put(textField.getName(), textField.getText());
        }
        return true;
    }
@@ -525,6 +551,21 @@
    public List<String> getPermittedTeams() {
        return teamsPalette.getSelections();
    }
    public void setCustomFields(RepositoryModel repository, List<String> customFields) {
        customFieldsPanel.removeAll();
        for (String customFieldDef : customFields) {
            String[] customFieldProperty = customFieldDef.split("=");
            String fieldName = customFieldProperty[0];
            String fieldLabel = customFieldProperty[1];
            JTextField textField = new JTextField(repository.customFields.get(fieldName), 50);
            textField.setName(fieldName);
            customFieldsPanel.add(newFieldPanel(fieldLabel, 250, textField));
        }
    }
    /**
     * ListCellRenderer to display descriptive text about the access
src/com/gitblit/client/RepositoriesPanel.java
@@ -47,6 +47,7 @@
import com.gitblit.Constants;
import com.gitblit.Constants.RpcRequest;
import com.gitblit.Keys;
import com.gitblit.models.FeedModel;
import com.gitblit.models.RepositoryModel;
import com.gitblit.utils.StringUtils;
@@ -430,6 +431,7 @@
                gitblit.getPreReceiveScriptsInherited(repository), repository.preReceiveScripts);
        dialog.setPostReceiveScripts(gitblit.getPostReceiveScriptsUnused(repository),
                gitblit.getPostReceiveScriptsInherited(repository), repository.postReceiveScripts);
        dialog.setCustomFields(repository, gitblit.getSettings().get(Keys.repository.customFields).getStrings());
        dialog.setVisible(true);
        final RepositoryModel revisedRepository = dialog.getRepository();
        final List<String> permittedUsers = dialog.getPermittedUsers();
src/com/gitblit/client/VerticalFlowLayout.java
New file
@@ -0,0 +1,496 @@
package com.gitblit.client;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
 * A flow layout arranges components in a directional flow, much
 * like lines of text in a paragraph. The flow direction is
 * determined by the container's <code>componentOrientation</code>
 * property and may be one of two values:
 * <ul>
 * <li><code>ComponentOrientation.TOP_TO_BOTTOM</code>
 * <li><code>ComponentOrientation.BOTTOM_TO_TOP</code>
 * </ul>
 * Flow layouts are typically used
 * to arrange buttons in a panel. It arranges buttons
 * horizontally until no more buttons fit on the same line.
 * The line alignment is determined by the <code>align</code>
 * property. The possible values are:
 * <ul>
 * <li>{@link #TOP TOP}
 * <li>{@link #BOTTOM BOTTOM}
 * <li>{@link #CENTER CENTER}
 * <li>{@link #LEADING LEADING}
 * <li>{@link #TRAILING TRAILING}
 * </ul>
 * <p>
 */
public class VerticalFlowLayout implements LayoutManager, java.io.Serializable
{
    /**
     * This value indicates that each row of components
     * should be left-justified.
     */
    public static final int TOP     = 0;
    /**
     * This value indicates that each row of components
     * should be centered.
     */
    public static final int CENTER    = 1;
    /**
     * This value indicates that each row of components
     * should be right-justified.
     */
    public static final int BOTTOM     = 2;
    /**
     * <code>align</code> is the property that determines
     * how each column distributes empty space.
     * It can be one of the following three values:
     * <ul>
     * <code>TOP</code>
     * <code>BOTTOM</code>
     * <code>CENTER</code>
     * </ul>
     *
     * @see #getAlignment
     * @see #setAlignment
     */
    int align;     // This is the one we actually use
    /**
     * The flow layout manager allows a seperation of
     * components with gaps.  The horizontal gap will
     * specify the space between components and between
     * the components and the borders of the
     * <code>Container</code>.
     *
     * @see #getHgap()
     * @see #setHgap(int)
     */
    int hgap;
    /**
     * The flow layout manager allows a seperation of
     * components with gaps.  The vertical gap will
     * specify the space between rows and between the
     * the rows and the borders of the <code>Container</code>.
     *
     * @see #getHgap()
     * @see #setHgap(int)
     */
    int vgap;
    /**
     * Constructs a new <code>VerticalFlowLayout</code> with a centered alignment and a
     * default 5-unit horizontal and vertical gap.
     */
    public VerticalFlowLayout()
    {
        this(CENTER, 5, 5);
    }
    /**
     * Constructs a new <code>VerticalFlowLayout</code> with the specified
     * alignment and a default 5-unit horizontal and vertical gap.
     * The value of the alignment argument must be one of
     * <code>VerticalFlowLayout.TOP</code>, <code>VerticalFlowLayout.BOTTOM</code>,
     * or <code>VerticalFlowLayout.CENTER</code>
     * @param align the alignment value
     */
    public VerticalFlowLayout(int align)
    {
        this(align, 5, 5);
    }
    /**
     * Creates a new flow layout manager with the indicated alignment
     * and the indicated horizontal and vertical gaps.
     * <p>
     * The value of the alignment argument must be one of
     * <code>VerticalFlowLayout.TOP</code>, <code>VerticalFlowLayout.BOTTOM</code>,
     * or <code>VerticalFlowLayout.CENTER</code>.
     * @param     align   the alignment value
     * @param     hgap  the horizontal gap between components
     *                   and between the components and the
     *                   borders of the <code>Container</code>
     * @param     vgap  the vertical gap between components
     *                   and between the components and the
     *                   borders of the <code>Container</code>
     */
    public VerticalFlowLayout(int align, int hgap, int vgap)
    {
        this.hgap = hgap;
        this.vgap = vgap;
        setAlignment(align);
    }
    /**
     * Gets the alignment for this layout.
     * Possible values are <code>VerticalFlowLayout.TOP</code>,
     * <code>VerticalFlowLayout.BOTTOM</code> or <code>VerticalFlowLayout.CENTER</code>,
     * @return   the alignment value for this layout
     * @see     java.awt.VerticalFlowLayout#setAlignment
     * @since     JDK1.1
     */
    public int getAlignment()
    {
        return align;
    }
    /**
     * Sets the alignment for this layout. Possible values are
     * <ul>
     * <li><code>VerticalFlowLayout.TOP</code>
     * <li><code>VerticalFlowLayout.BOTTOM</code>
     * <li><code>VerticalFlowLayout.CENTER</code>
     * </ul>
     * @param     align one of the alignment values shown above
     * @see     #getAlignment()
     * @since     JDK1.1
     */
    public void setAlignment(int align)
    {
        this.align = align;
    }
    /**
     * Gets the horizontal gap between components
     * and between the components and the borders
     * of the <code>Container</code>
     *
     * @return   the horizontal gap between components
     *           and between the components and the borders
     *           of the <code>Container</code>
     * @see     java.awt.VerticalFlowLayout#setHgap
     * @since     JDK1.1
     */
    public int getHgap() {
        return hgap;
    }
    /**
     * Sets the horizontal gap between components and
     * between the components and the borders of the
     * <code>Container</code>.
     *
     * @param hgap the horizontal gap between components
     *           and between the components and the borders
     *           of the <code>Container</code>
     * @see     java.awt.VerticalFlowLayout#getHgap
     * @since     JDK1.1
     */
    public void setHgap(int hgap) {
        this.hgap = hgap;
    }
    /**
     * Gets the vertical gap between components and
     * between the components and the borders of the
     * <code>Container</code>.
     *
     * @return   the vertical gap between components
     *           and between the components and the borders
     *           of the <code>Container</code>
     * @see     java.awt.VerticalFlowLayout#setVgap
     * @since     JDK1.1
     */
    public int getVgap() {
        return vgap;
    }
    /**
     * Sets the vertical gap between components and between
     * the components and the borders of the <code>Container</code>.
     *
     * @param vgap the vertical gap between components
     *           and between the components and the borders
     *           of the <code>Container</code>
     * @see     java.awt.VerticalFlowLayout#getVgap
     */
    public void setVgap(int vgap) {
        this.vgap = vgap;
    }
    /**
     * Adds the specified component to the layout.
     * Not used by this class.
     * @param name the name of the component
     * @param comp the component to be added
     */
    public void addLayoutComponent(String name, Component comp) {
    }
    /**
     * Removes the specified component from the layout.
     * Not used by this class.
     * @param comp the component to remove
     * @see    java.awt.Container#removeAll
     */
    public void removeLayoutComponent(Component comp) {
    }
    /**
     * Returns the preferred dimensions for this layout given the
     * <i>visible</i> components in the specified target container.
     *
     * @param target the container that needs to be laid out
     * @return  the preferred dimensions to lay out the
     *          subcomponents of the specified container
     * @see Container
     * @see #minimumLayoutSize
     * @see    java.awt.Container#getPreferredSize
     */
    public Dimension preferredLayoutSize(Container target)
    {
    synchronized (target.getTreeLock())
    {
        Dimension dim = new Dimension(0, 0);
        int nmembers = target.getComponentCount();
        boolean firstVisibleComponent = true;
        for (int i = 0 ; i < nmembers ; i++)
        {
            Component m = target.getComponent(i);
            if (m.isVisible())
            {
                Dimension d = m.getPreferredSize();
                dim.width = Math.max(dim.width, d.width);
                if (firstVisibleComponent)
                {
                    firstVisibleComponent = false;
                }
                else
                {
                    dim.height += vgap;
                }
                dim.height += d.height;
            }
        }
        Insets insets = target.getInsets();
        dim.width += insets.left + insets.right + hgap*2;
        dim.height += insets.top + insets.bottom + vgap*2;
        return dim;
    }
    }
    /**
     * Returns the minimum dimensions needed to layout the <i>visible</i>
     * components contained in the specified target container.
     * @param target the container that needs to be laid out
     * @return  the minimum dimensions to lay out the
     *          subcomponents of the specified container
     * @see #preferredLayoutSize
     * @see    java.awt.Container
     * @see    java.awt.Container#doLayout
     */
    public Dimension minimumLayoutSize(Container target)
    {
    synchronized (target.getTreeLock())
    {
        Dimension dim = new Dimension(0, 0);
        int nmembers = target.getComponentCount();
        boolean firstVisibleComponent = true;
        for (int i = 0 ; i < nmembers ; i++)
        {
            Component m = target.getComponent(i);
            if (m.isVisible())
            {
                Dimension d = m.getMinimumSize();
                dim.width = Math.max(dim.width, d.width);
                if (firstVisibleComponent)
                {
                    firstVisibleComponent = false;
                }
                else
                {
                    dim.height += vgap;
                }
                dim.height += d.height;
            }
        }
        Insets insets = target.getInsets();
        dim.width += insets.left + insets.right + hgap*2;
        dim.height += insets.top + insets.bottom + vgap*2;
        return dim;
    }
    }
    /**
     * Lays out the container. This method lets each
     * <i>visible</i> component take
     * its preferred size by reshaping the components in the
     * target container in order to satisfy the alignment of
     * this <code>VerticalFlowLayout</code> object.
     *
     * @param target the specified component being laid out
     * @see Container
     * @see    java.awt.Container#doLayout
     */
    public void layoutContainer(Container target)
    {
    synchronized (target.getTreeLock())
    {
        Insets insets = target.getInsets();
        int maxHeight = target.getSize().height - (insets.top + insets.bottom + vgap*2);
        int nmembers = target.getComponentCount();
        int x = insets.left + hgap;
        int y = 0;
        int columnWidth = 0;
        int start = 0;
        boolean ttb = target.getComponentOrientation().isLeftToRight();
        for (int i = 0 ; i < nmembers ; i++)
        {
            Component m = target.getComponent(i);
            if (m.isVisible())
            {
                Dimension d = m.getPreferredSize();
                m.setSize(d.width, d.height);
                if ((y == 0) || ((y + d.height) <= maxHeight))
                {
                    if (y > 0)
                    {
                        y += vgap;
                    }
                    y += d.height;
                    columnWidth = Math.max(columnWidth, d.width);
                }
                else
                {
                    moveComponents(target, x, insets.top + vgap, columnWidth, maxHeight - y, start, i, ttb);
                    y = d.height;
                    x += hgap + columnWidth;
                    columnWidth = d.width;
                    start = i;
                }
            }
        }
        moveComponents(target, x, insets.top + vgap, columnWidth, maxHeight - y, start, nmembers, ttb);
    }
    }
    /**
     * Centers the elements in the specified row, if there is any slack.
     * @param target the component which needs to be moved
     * @param x the x coordinate
     * @param y the y coordinate
     * @param width the width dimensions
     * @param height the height dimensions
     * @param columnStart the beginning of the column
     * @param columnEnd the the ending of the column
     */
    private void moveComponents(
        Container target, int x, int y, int width, int height, int columnStart, int columnEnd, boolean ttb)
    {
        switch (align)
        {
            case TOP:
                y += ttb ? 0 : height;
                break;
            case CENTER:
                y += height / 2;
                break;
            case BOTTOM:
                y += ttb ? height : 0;
                break;
        }
        for (int i = columnStart ; i < columnEnd ; i++)
        {
            Component m = target.getComponent(i);
            if (m.isVisible())
            {
                int cx;
                cx = x + (width - m.getSize().width) / 2;
                if (ttb)
                {
                    m.setLocation(cx, y);
                }
                else
                {
                    m.setLocation(cx, target.getSize().height - y - m.getSize().height);
                }
                y += m.getSize().height + vgap;
            }
        }
    }
    /**
     * Returns a string representation of this <code>VerticalFlowLayout</code>
     * object and its values.
     * @return   a string representation of this layout
     */
    public String toString()
    {
        String str = "";
        switch (align)
        {
            case TOP:    str = ",align=top"; break;
            case CENTER: str = ",align=center"; break;
            case BOTTOM: str = ",align=bottom"; break;
        }
        return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + str + "]";
    }
    public static void main(String[] args)
    {
        JPanel main = new JPanel( new BorderLayout() );
        final JPanel buttons = new JPanel(new VerticalFlowLayout() );
//      buttons.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
        main.add(buttons, BorderLayout.CENTER);
        for (int i = 0; i < 7; i++)
        {
            buttons.add( new JRadioButton("button " + i) );
        }
        JButton button = new JButton("Add Radio Button");
        main.add(button, BorderLayout.SOUTH);
        button.addActionListener( new ActionListener()
        {
            private int i = 8;
            public void actionPerformed(ActionEvent e)
            {
                buttons.add( new JRadioButton("button R Us" + i++) );
                buttons.revalidate();
//              pack();
            }
        });
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(main);
        frame.setSize(300, 300);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}