build.xml | ●●●●● patch | view | raw | blame | history | |
resources/settings_16x16.png | patch | view | raw | blame | history | |
src/com/gitblit/client/GitblitManager.java | ●●●●● patch | view | raw | blame | history | |
src/com/gitblit/client/GitblitPanel.java | ●●●●● patch | view | raw | blame | history | |
src/com/gitblit/client/HeaderPanel.java | ●●●●● patch | view | raw | blame | history | |
src/com/gitblit/client/SettingsModel.java | ●●●●● patch | view | raw | blame | history | |
src/com/gitblit/client/Utils.java | ●●●●● patch | view | raw | blame | history | |
src/com/gitblit/wicket/GitBlitWebApp.properties | ●●●●● patch | view | raw | blame | history |
build.xml
@@ -428,6 +428,9 @@ <genjar jarfile="manager.jar"> <resource file="${basedir}/src/com/gitblit/client/splash.png" /> <resource file="${basedir}/resources/gitblt-favicon.png" /> <resource file="${basedir}/resources/gitweb-favicon.png" /> <resource file="${basedir}/resources/user_16x16.png" /> <resource file="${basedir}/resources/settings_16x16.png" /> <resource file="${basedir}/resources/lock_go_16x16.png" /> <resource file="${basedir}/resources/lock_pull_16x16.png" /> <resource file="${basedir}/resources/shield_16x16.png" /> resources/settings_16x16.png
src/com/gitblit/client/GitblitManager.java
@@ -20,12 +20,18 @@ import java.awt.EventQueue; import java.awt.Font; import java.awt.GridLayout; import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.text.MessageFormat; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import javax.swing.ImageIcon; import javax.swing.JFrame; @@ -41,11 +47,17 @@ import javax.swing.KeyStroke; import javax.swing.UIManager; import org.eclipse.jgit.errors.ConfigInvalidException; import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.util.Base64; import org.eclipse.jgit.util.FS; import com.gitblit.Constants; import com.gitblit.utils.StringUtils; /** * Sample RPC application. * Gitblit Manager issues JSON RPC requests to a Gitblit server. * * @author James Moger * @@ -54,10 +66,11 @@ private static final long serialVersionUID = 1L; private JTabbedPane serverTabs; private File configFile = new File(System.getProperty("user.home"), ".gitblit/config"); private GitblitRegistration localhost = new GitblitRegistration("default", "https://localhost:8443", "admin", "admin".toCharArray()); private List<GitblitRegistration> registrations = new ArrayList<GitblitRegistration>(); private Map<String, GitblitRegistration> registrations = new LinkedHashMap<String, GitblitRegistration>(); private JMenu recentMenu; private GitblitManager() { @@ -67,10 +80,66 @@ private void initialize() { setContentPane(getCenterPanel()); setIconImage(new ImageIcon(getClass().getResource("/gitblt-favicon.png")).getImage()); setTitle("Gitblit Manager v" + Constants.VERSION + " (" + Constants.VERSION_DATE + ")"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(800, 500); addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent event) { saveSizeAndPosition(); } }); setSizeAndPosition(); loadRegistrations(); rebuildRecentMenu(); } private void setSizeAndPosition() { String sz = null; String pos = null; try { StoredConfig config = getConfig(); sz = config.getString("ui", null, "size"); pos = config.getString("ui", null, "position"); } catch (Throwable t) { t.printStackTrace(); } // try to restore saved window size if (StringUtils.isEmpty(sz)) { setSize(850, 500); } else { String[] chunks = sz.split("x"); int width = Integer.parseInt(chunks[0]); int height = Integer.parseInt(chunks[1]); setSize(width, height); } // try to restore saved window position if (StringUtils.isEmpty(pos)) { setLocationRelativeTo(null); } else { String[] chunks = pos.split(","); int x = Integer.parseInt(chunks[0]); int y = Integer.parseInt(chunks[1]); setLocation(x, y); } } private void saveSizeAndPosition() { try { // save window size and position StoredConfig config = getConfig(); Dimension sz = GitblitManager.this.getSize(); config.setString("ui", null, "size", MessageFormat.format("{0,number,0}x{1,number,0}", sz.width, sz.height)); Point pos = GitblitManager.this.getLocationOnScreen(); config.setString("ui", null, "position", MessageFormat.format("{0,number,0},{1,number,0}", pos.x, pos.y)); config.save(); } catch (Throwable t) { Utils.showException(GitblitManager.this, t); } } public void setVisible(boolean value) { @@ -80,10 +149,10 @@ loginPrompt(localhost); } else if (registrations.size() == 1) { // single registration prompt loginPrompt(registrations.get(0)); GitblitRegistration reg = registrations.values().iterator().next(); loginPrompt(reg); } super.setVisible(value); setLocationRelativeTo(null); } } @@ -147,7 +216,7 @@ reg = new GitblitRegistration(nameField.getText(), url, accountField.getText(), passwordField.getPassword()); boolean success = login(reg); registrations.add(0, reg); registrations.put(reg.name, reg); rebuildRecentMenu(); return success; } @@ -161,6 +230,7 @@ serverTabs.setSelectedIndex(idx); serverTabs.setTabComponentAt(idx, new ClosableTabComponent(reg.name, null, serverTabs, panel)); saveRegistration(reg); return true; } catch (IOException e) { JOptionPane.showMessageDialog(GitblitManager.this, e.getMessage(), @@ -171,17 +241,54 @@ private void rebuildRecentMenu() { recentMenu.removeAll(); for (final GitblitRegistration reg : registrations) { JMenuItem item = new JMenuItem(reg.name); ImageIcon icon = new ImageIcon(getClass().getResource("/gitblt-favicon.png")); for (final GitblitRegistration reg : registrations.values()) { JMenuItem item = new JMenuItem(reg.name, icon); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { login(reg); loginPrompt(reg); } }); recentMenu.add(item); } } private void loadRegistrations() { try { StoredConfig config = getConfig(); Set<String> servers = config.getSubsections("servers"); for (String server : servers) { String url = config.getString("servers", server, "url"); String account = config.getString("servers", server, "account"); char[] password = new String(Base64.decode(config.getString("servers", server, "password"))).toCharArray(); GitblitRegistration reg = new GitblitRegistration(server, url, account, password); registrations.put(reg.name, reg); } } catch (Throwable t) { Utils.showException(GitblitManager.this, t); } } private void saveRegistration(GitblitRegistration reg) { try { StoredConfig config = getConfig(); config.setString("servers", reg.name, "url", reg.url); config.setString("servers", reg.name, "account", reg.account); config.setString("servers", reg.name, "password", Base64.encodeBytes(new String(reg.password).getBytes("UTF-8"))); config.save(); } catch (Throwable t) { Utils.showException(GitblitManager.this, t); } } private StoredConfig getConfig() throws IOException, ConfigInvalidException { FileBasedConfig config = new FileBasedConfig(configFile, FS.detect()); config.load(); return config; } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { src/com/gitblit/client/GitblitPanel.java
@@ -80,6 +80,10 @@ private UsersModel usersModel; private JTable settingsTable; private SettingsModel settingsModel; private JButton createRepository; private JButton delRepository; @@ -96,6 +100,8 @@ private TableRowSorter<UsersModel> defaultUsersSorter; private TableRowSorter<SettingsModel> defaultSettingsSorter; private JButton editRepository; public GitblitPanel(GitblitRegistration reg) { @@ -105,6 +111,17 @@ public GitblitPanel(String url, String account, char[] password) { this.gitblit = new GitblitModel(url, account, password); tabs = new JTabbedPane(JTabbedPane.BOTTOM); tabs.addTab(Translation.get("gb.repositories"), createRepositoriesPanel()); tabs.addTab(Translation.get("gb.users"), createUsersPanel()); tabs.addTab(Translation.get("gb.federation"), new JPanel()); tabs.addTab(Translation.get("gb.settings"), createSettingsPanel()); setLayout(new BorderLayout()); add(tabs, BorderLayout.CENTER); } private JPanel createRepositoriesPanel() { final JButton browseRepository = new JButton(Translation.get("gb.browse")); browseRepository.setEnabled(false); browseRepository.addActionListener(new ActionListener() { @@ -168,10 +185,10 @@ repositoriesTable.setRowSorter(defaultRepositoriesSorter); repositoriesTable.getRowSorter().toggleSortOrder(RepositoriesModel.Columns.Name.ordinal()); setRepositoryRenderer(RepositoriesModel.Columns.Name, nameRenderer); setRepositoryRenderer(RepositoriesModel.Columns.Indicators, typeRenderer); setRepositoryRenderer(RepositoriesModel.Columns.Owner, ownerRenderer); setRepositoryRenderer(RepositoriesModel.Columns.Size, sizeRenderer); setRepositoryRenderer(RepositoriesModel.Columns.Name, nameRenderer, -1); setRepositoryRenderer(RepositoriesModel.Columns.Indicators, typeRenderer, 100); setRepositoryRenderer(RepositoriesModel.Columns.Owner, ownerRenderer, -1); setRepositoryRenderer(RepositoriesModel.Columns.Size, sizeRenderer, 60); repositoriesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override @@ -231,11 +248,25 @@ return insets; } }; repositoriesPanel.add(new HeaderPanel(Translation.get("gb.repositories")), BorderLayout.NORTH); repositoriesPanel.add(new HeaderPanel(Translation.get("gb.repositories"), "gitweb-favicon.png"), BorderLayout.NORTH); repositoriesPanel.add(repositoryTablePanel, BorderLayout.CENTER); repositoriesPanel.add(repositoryControls, BorderLayout.SOUTH); return repositoriesPanel; } private void setRepositoryRenderer(RepositoriesModel.Columns col, TableCellRenderer renderer, int maxWidth) { String name = repositoriesTable.getColumnName(col.ordinal()); repositoriesTable.getColumn(name).setCellRenderer(renderer); if (maxWidth > 0) { repositoriesTable.getColumn(name).setMinWidth(maxWidth); repositoriesTable.getColumn(name).setMaxWidth(maxWidth); } } private JPanel createUsersPanel() { JButton refreshUsers = new JButton(Translation.get("gb.refresh")); refreshUsers.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -322,22 +353,73 @@ return insets; } }; usersPanel.add(new HeaderPanel(Translation.get("gb.users")), BorderLayout.NORTH); usersPanel.add(new HeaderPanel(Translation.get("gb.users"), "user_16x16.png"), BorderLayout.NORTH); usersPanel.add(userTablePanel, BorderLayout.CENTER); usersPanel.add(userControls, BorderLayout.SOUTH); tabs = new JTabbedPane(JTabbedPane.BOTTOM); tabs.addTab(Translation.get("gb.repositories"), repositoriesPanel); tabs.addTab(Translation.get("gb.users"), usersPanel); tabs.addTab(Translation.get("gb.federation"), new JPanel()); setLayout(new BorderLayout()); add(tabs, BorderLayout.CENTER); return usersPanel; } private void setRepositoryRenderer(RepositoriesModel.Columns col, TableCellRenderer renderer) { String name = repositoriesTable.getColumnName(col.ordinal()); repositoriesTable.getColumn(name).setCellRenderer(renderer); private JPanel createSettingsPanel() { settingsModel = new SettingsModel(); defaultSettingsSorter = new TableRowSorter<SettingsModel>(settingsModel); settingsTable = Utils.newTable(settingsModel); String name = settingsTable.getColumnName(UsersModel.Columns.Name.ordinal()); settingsTable.setRowHeight(nameRenderer.getFont().getSize() + 8); settingsTable.getColumn(name).setCellRenderer(nameRenderer); settingsTable.setRowSorter(defaultSettingsSorter); settingsTable.getRowSorter().toggleSortOrder(SettingsModel.Columns.Name.ordinal()); settingsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting()) { return; } boolean selected = settingsTable.getSelectedRow() > -1; boolean singleSelection = settingsTable.getSelectedRows().length == 1; // TODO enable/disable setting buttons } }); final JTextField settingFilter = new JTextField(); settingFilter.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { filterSettings(settingFilter.getText()); } }); settingFilter.addKeyListener(new KeyAdapter() { public void keyReleased(KeyEvent e) { filterSettings(settingFilter.getText()); } }); JPanel settingFilterPanel = new JPanel(new BorderLayout(margin, margin)); settingFilterPanel.add(new JLabel(Translation.get("gb.filter")), BorderLayout.WEST); settingFilterPanel.add(settingFilter, BorderLayout.CENTER); JPanel settingsTablePanel = new JPanel(new BorderLayout(margin, margin)); settingsTablePanel.add(settingFilterPanel, BorderLayout.NORTH); settingsTablePanel.add(new JScrollPane(settingsTable), BorderLayout.CENTER); JPanel settingsControls = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0)); // TODO update setting? JPanel settingsPanel = new JPanel(new BorderLayout(margin, margin)) { private static final long serialVersionUID = 1L; public Insets getInsets() { return insets; } }; settingsPanel.add(new HeaderPanel(Translation.get("gb.settings"), "settings_16x16.png"), BorderLayout.NORTH); settingsPanel.add(settingsTablePanel, BorderLayout.CENTER); settingsPanel.add(settingsControls, BorderLayout.SOUTH); return settingsPanel; } public void login() throws IOException { @@ -348,6 +430,7 @@ if (gitblit.allowAdmin()) { updateUsersTable(); updateSettingsTable(); } else { // user does not have administrator privileges // hide admin repository buttons @@ -372,6 +455,11 @@ usersModel.list.clear(); usersModel.list.addAll(gitblit.getUsers()); usersModel.fireTableDataChanged(); } private void updateSettingsTable() { settingsModel.setSettings(gitblit.getSettings()); settingsModel.fireTableDataChanged(); } private void filterRepositories(final String fragment) { @@ -413,6 +501,26 @@ TableRowSorter<UsersModel> sorter = new TableRowSorter<UsersModel>(usersModel); sorter.setRowFilter(containsFilter); usersTable.setRowSorter(sorter); } private void filterSettings(final String fragment) { if (StringUtils.isEmpty(fragment)) { settingsTable.setRowSorter(defaultSettingsSorter); return; } RowFilter<SettingsModel, Object> containsFilter = new RowFilter<SettingsModel, Object>() { public boolean include(Entry<? extends SettingsModel, ? extends Object> entry) { for (int i = entry.getValueCount() - 1; i >= 0; i--) { if (entry.getStringValue(i).toLowerCase().contains(fragment.toLowerCase())) { return true; } } return false; } }; TableRowSorter<SettingsModel> sorter = new TableRowSorter<SettingsModel>(settingsModel); sorter.setRowFilter(containsFilter); settingsTable.setRowSorter(sorter); } private List<RepositoryModel> getSelectedRepositories() { @@ -572,6 +680,7 @@ success &= gitblit.deleteRepository(repository); } if (success) { gitblit.refreshRepositories(); gitblit.refreshUsers(); } return success; src/com/gitblit/client/HeaderPanel.java
@@ -15,6 +15,7 @@ */ package com.gitblit.client; import java.awt.BasicStroke; import java.awt.Color; import java.awt.FlowLayout; import java.awt.GradientPaint; @@ -24,8 +25,11 @@ import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; import com.gitblit.utils.StringUtils; public class HeaderPanel extends JPanel { @@ -33,12 +37,15 @@ private Color lightColor = new Color(0, 0, 0x60); public HeaderPanel(String text) { public HeaderPanel(String text, String icon) { super(new FlowLayout(FlowLayout.LEFT), true); setOpaque(true); setBackground(new Color(0, 0, 0x20)); JLabel label = new JLabel(text); if (!StringUtils.isEmpty(icon)) { label.setIcon(new ImageIcon(getClass().getResource("/" + icon))); } label.setForeground(Color.white); label.setFont(label.getFont().deriveFont(14f)); add(label); @@ -53,5 +60,9 @@ false); g.setPaint(gradientPaint); g.fill(new Rectangle2D.Double(0, 0, getWidth(), getHeight())); g.setColor(new Color(0xff, 0x99, 0x00)); int stroke = 2; g.setStroke(new BasicStroke(stroke)); g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); } } src/com/gitblit/client/SettingsModel.java
New file @@ -0,0 +1,110 @@ /* * Copyright 2011 gitblit.com. * * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 * * 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 com.gitblit.client; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.swing.table.AbstractTableModel; import com.gitblit.IStoredSettings; /** * Table model of IStoredSettings. * * @author James Moger * */ public class SettingsModel extends AbstractTableModel { private static final long serialVersionUID = 1L; IStoredSettings settings; List<String> keys; enum Columns { Name, Value; @Override public String toString() { return name().replace('_', ' '); } } public SettingsModel() { this(null); } public SettingsModel(IStoredSettings settings) { setSettings(settings); } public void setSettings(IStoredSettings settings) { this.settings = settings; if (settings == null) { keys = new ArrayList<String>(); } else { keys = new ArrayList<String>(settings.getAllKeys(null)); Collections.sort(keys); } } @Override public int getRowCount() { return keys.size(); } @Override public int getColumnCount() { return Columns.values().length; } @Override public String getColumnName(int column) { Columns col = Columns.values()[column]; switch (col) { case Name: return Translation.get("gb.name"); } return ""; } /** * Returns <code>Object.class</code> regardless of <code>columnIndex</code>. * * @param columnIndex * the column being queried * @return the Object.class */ public Class<?> getColumnClass(int columnIndex) { return String.class; } @Override public Object getValueAt(int rowIndex, int columnIndex) { String key = keys.get(rowIndex); Columns col = Columns.values()[columnIndex]; switch (col) { case Name: return key; case Value: return settings.getString(key, ""); } return null; } } src/com/gitblit/client/Utils.java
@@ -56,6 +56,7 @@ public static void showException(Component c, Throwable t) { // TODO show the unexpected exception t.printStackTrace(); } public static void packColumns(JTable table, int margin) { src/com/gitblit/wicket/GitBlitWebApp.properties
@@ -155,4 +155,5 @@ gb.downloading = downloading gb.loading = loading gb.starting = starting gb.general = general gb.general = general gb.settings = settings