import java.text.MessageFormat;\r
import java.util.ArrayList;\r
import java.util.Arrays;\r
+import java.util.HashMap;\r
import java.util.HashSet;\r
import java.util.List;\r
import java.util.Set;\r
import javax.swing.JOptionPane;\r
import javax.swing.JPanel;\r
import javax.swing.JRootPane;\r
+import javax.swing.JScrollPane;\r
import javax.swing.JTabbedPane;\r
import javax.swing.JTextField;\r
import javax.swing.KeyStroke;\r
import javax.swing.ListCellRenderer;\r
+import javax.swing.ScrollPaneConstants;\r
\r
import com.gitblit.Constants.AccessRestrictionType;\r
import com.gitblit.Constants.FederationStrategy;\r
private JLabel postReceiveInherited;\r
\r
private Set<String> repositoryNames;\r
+ \r
+ private JPanel customFieldsPanel;\r
\r
public EditRepositoryDialog(int protocolVersion) {\r
this(protocolVersion, new RepositoryModel());\r
JPanel postReceivePanel = new JPanel(new BorderLayout(5, 5));\r
postReceivePanel.add(postReceivePalette, BorderLayout.CENTER);\r
postReceivePanel.add(postReceiveInherited, BorderLayout.WEST);\r
+ \r
+ customFieldsPanel = new JPanel(new VerticalFlowLayout());\r
+ JScrollPane customFieldsScrollPane = new JScrollPane(customFieldsPanel);\r
+ customFieldsScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);\r
+ customFieldsScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);\r
\r
JTabbedPane panel = new JTabbedPane(JTabbedPane.TOP);\r
panel.addTab(Translation.get("gb.general"), fieldsPanel);\r
}\r
panel.addTab(Translation.get("gb.preReceiveScripts"), preReceivePanel);\r
panel.addTab(Translation.get("gb.postReceiveScripts"), postReceivePanel);\r
+ \r
+ panel.addTab(Translation.get("gb.customFields"), customFieldsScrollPane);\r
+ \r
\r
JButton createButton = new JButton(Translation.get("gb.save"));\r
createButton.addActionListener(new ActionListener() {\r
pack();\r
nameField.requestFocus();\r
}\r
-\r
+ \r
private JPanel newFieldPanel(String label, JComponent comp) {\r
+ return newFieldPanel(label, 150, comp);\r
+ }\r
+\r
+ private JPanel newFieldPanel(String label, int labelSize, JComponent comp) {\r
JLabel fieldLabel = new JLabel(label);\r
fieldLabel.setFont(fieldLabel.getFont().deriveFont(Font.BOLD));\r
- fieldLabel.setPreferredSize(new Dimension(150, 20));\r
+ fieldLabel.setPreferredSize(new Dimension(labelSize, 20));\r
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 0));\r
panel.add(fieldLabel);\r
panel.add(comp);\r
repository.indexedBranches = indexedBranchesPalette.getSelections();\r
repository.preReceiveScripts = preReceivePalette.getSelections();\r
repository.postReceiveScripts = postReceivePalette.getSelections();\r
+ \r
+ // Custom Fields\r
+ repository.customFields = new HashMap<String, String>();\r
+ \r
+ for (Component aCustomFieldPanel : customFieldsPanel.getComponents()) {\r
+ JTextField textField = (JTextField) ((JPanel)aCustomFieldPanel).getComponent(1);\r
+ repository.customFields.put(textField.getName(), textField.getText());\r
+ }\r
+ \r
return true;\r
}\r
\r
public List<String> getPermittedTeams() {\r
return teamsPalette.getSelections();\r
}\r
+ \r
+ public void setCustomFields(RepositoryModel repository, List<String> customFields) {\r
+ customFieldsPanel.removeAll();\r
+ \r
+ for (String customFieldDef : customFields) {\r
+ String[] customFieldProperty = customFieldDef.split("=");\r
+ String fieldName = customFieldProperty[0];\r
+ String fieldLabel = customFieldProperty[1];\r
+ \r
+ JTextField textField = new JTextField(repository.customFields.get(fieldName), 50);\r
+ textField.setName(fieldName);\r
+ \r
+ customFieldsPanel.add(newFieldPanel(fieldLabel, 250, textField));\r
+ }\r
+ }\r
\r
/**\r
* ListCellRenderer to display descriptive text about the access\r
--- /dev/null
+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);
+ }
+
+
+}
\ No newline at end of file