From 0e6eace75d39ef300891b529d471617b5da8cfaa Mon Sep 17 00:00:00 2001 From: John Crygier Date: Mon, 7 May 2012 09:58:56 -0500 Subject: Add custom fields to the manager --- src/com/gitblit/client/EditRepositoryDialog.java | 45 +- src/com/gitblit/client/RepositoriesPanel.java | 2 + src/com/gitblit/client/VerticalFlowLayout.java | 496 +++++++++++++++++++++++ 3 files changed, 541 insertions(+), 2 deletions(-) create mode 100644 src/com/gitblit/client/VerticalFlowLayout.java diff --git a/src/com/gitblit/client/EditRepositoryDialog.java b/src/com/gitblit/client/EditRepositoryDialog.java index 156de15d..6ad75c6c 100644 --- a/src/com/gitblit/client/EditRepositoryDialog.java +++ b/src/com/gitblit/client/EditRepositoryDialog.java @@ -28,6 +28,7 @@ import java.awt.event.KeyEvent; 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.JList; 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 @@ public class EditRepositoryDialog extends JDialog { private JLabel postReceiveInherited; private Set repositoryNames; + + private JPanel customFieldsPanel; public EditRepositoryDialog(int protocolVersion) { this(protocolVersion, new RepositoryModel()); @@ -277,6 +282,11 @@ public class EditRepositoryDialog extends JDialog { 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 @@ public class EditRepositoryDialog extends JDialog { } 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 @@ public class EditRepositoryDialog extends JDialog { 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 @@ public class EditRepositoryDialog extends JDialog { repository.indexedBranches = indexedBranchesPalette.getSelections(); repository.preReceiveScripts = preReceivePalette.getSelections(); repository.postReceiveScripts = postReceivePalette.getSelections(); + + // Custom Fields + repository.customFields = new HashMap(); + + 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 class EditRepositoryDialog extends JDialog { public List getPermittedTeams() { return teamsPalette.getSelections(); } + + public void setCustomFields(RepositoryModel repository, List 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 diff --git a/src/com/gitblit/client/RepositoriesPanel.java b/src/com/gitblit/client/RepositoriesPanel.java index 685a70a6..89ec6054 100644 --- a/src/com/gitblit/client/RepositoriesPanel.java +++ b/src/com/gitblit/client/RepositoriesPanel.java @@ -47,6 +47,7 @@ import javax.swing.table.TableRowSorter; 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 @@ public abstract class RepositoriesPanel extends JPanel { 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 permittedUsers = dialog.getPermittedUsers(); diff --git a/src/com/gitblit/client/VerticalFlowLayout.java b/src/com/gitblit/client/VerticalFlowLayout.java new file mode 100644 index 00000000..d799cb36 --- /dev/null +++ b/src/com/gitblit/client/VerticalFlowLayout.java @@ -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 componentOrientation + * property and may be one of two values: + *
    + *
  • ComponentOrientation.TOP_TO_BOTTOM + *
  • ComponentOrientation.BOTTOM_TO_TOP + *
+ * 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 align + * property. The possible values are: + *
    + *
  • {@link #TOP TOP} + *
  • {@link #BOTTOM BOTTOM} + *
  • {@link #CENTER CENTER} + *
  • {@link #LEADING LEADING} + *
  • {@link #TRAILING TRAILING} + *
+ *

+ */ +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; + + /** + * align is the property that determines + * how each column distributes empty space. + * It can be one of the following three values: + *

    + * TOP + * BOTTOM + * CENTER + *
+ * + * @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 + * Container. + * + * @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 Container. + * + * @see #getHgap() + * @see #setHgap(int) + */ + int vgap; + + /** + * Constructs a new VerticalFlowLayout with a centered alignment and a + * default 5-unit horizontal and vertical gap. + */ + public VerticalFlowLayout() + { + this(CENTER, 5, 5); + } + + /** + * Constructs a new VerticalFlowLayout with the specified + * alignment and a default 5-unit horizontal and vertical gap. + * The value of the alignment argument must be one of + * VerticalFlowLayout.TOP, VerticalFlowLayout.BOTTOM, + * or VerticalFlowLayout.CENTER + * @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. + *

+ * The value of the alignment argument must be one of + * VerticalFlowLayout.TOP, VerticalFlowLayout.BOTTOM, + * or VerticalFlowLayout.CENTER. + * @param align the alignment value + * @param hgap the horizontal gap between components + * and between the components and the + * borders of the Container + * @param vgap the vertical gap between components + * and between the components and the + * borders of the Container + */ + 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 VerticalFlowLayout.TOP, + * VerticalFlowLayout.BOTTOM or VerticalFlowLayout.CENTER, + * @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 + *

    + *
  • VerticalFlowLayout.TOP + *
  • VerticalFlowLayout.BOTTOM + *
  • VerticalFlowLayout.CENTER + *
+ * @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 Container + * + * @return the horizontal gap between components + * and between the components and the borders + * of the Container + * @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 + * Container. + * + * @param hgap the horizontal gap between components + * and between the components and the borders + * of the Container + * @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 + * Container. + * + * @return the vertical gap between components + * and between the components and the borders + * of the Container + * @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 Container. + * + * @param vgap the vertical gap between components + * and between the components and the borders + * of the Container + * @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 + * visible 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 visible + * 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 + * visible component take + * its preferred size by reshaping the components in the + * target container in order to satisfy the alignment of + * this VerticalFlowLayout 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 VerticalFlowLayout + * 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 -- cgit v1.2.3