From: James Moger Date: Tue, 18 Oct 2011 21:01:22 +0000 (-0400) Subject: Added icons and polish. Save and load gitblit registrations. X-Git-Tag: v0.7.0~71 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=ee25c8391c07dc59dc7cb9b3ff8b1b30dcbd2fcd;p=gitblit.git Added icons and polish. Save and load gitblit registrations. --- diff --git a/build.xml b/build.xml index 5ed87d5a..92174d4c 100644 --- a/build.xml +++ b/build.xml @@ -428,6 +428,9 @@ + + + diff --git a/resources/settings_16x16.png b/resources/settings_16x16.png new file mode 100644 index 00000000..1619e3de Binary files /dev/null and b/resources/settings_16x16.png differ diff --git a/src/com/gitblit/client/GitblitManager.java b/src/com/gitblit/client/GitblitManager.java index f777fdb7..47ff6eab 100644 --- a/src/com/gitblit/client/GitblitManager.java +++ b/src/com/gitblit/client/GitblitManager.java @@ -20,12 +20,18 @@ import java.awt.Dimension; 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.JTextField; 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 @@ public class GitblitManager extends JFrame { 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 registrations = new ArrayList(); + private Map registrations = new LinkedHashMap(); private JMenu recentMenu; private GitblitManager() { @@ -67,10 +80,66 @@ public class GitblitManager extends JFrame { 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 @@ public class GitblitManager extends JFrame { 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 @@ public class GitblitManager extends JFrame { 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 @@ public class GitblitManager extends JFrame { 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 @@ public class GitblitManager extends JFrame { 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 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() { diff --git a/src/com/gitblit/client/GitblitPanel.java b/src/com/gitblit/client/GitblitPanel.java index 5525e414..7bcaac5b 100644 --- a/src/com/gitblit/client/GitblitPanel.java +++ b/src/com/gitblit/client/GitblitPanel.java @@ -80,6 +80,10 @@ public class GitblitPanel extends JPanel implements CloseTabListener { private UsersModel usersModel; + private JTable settingsTable; + + private SettingsModel settingsModel; + private JButton createRepository; private JButton delRepository; @@ -96,6 +100,8 @@ public class GitblitPanel extends JPanel implements CloseTabListener { private TableRowSorter defaultUsersSorter; + private TableRowSorter defaultSettingsSorter; + private JButton editRepository; public GitblitPanel(GitblitRegistration reg) { @@ -105,6 +111,17 @@ public class GitblitPanel extends JPanel implements CloseTabListener { 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 @@ public class GitblitPanel extends JPanel implements CloseTabListener { 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 @@ public class GitblitPanel extends JPanel implements CloseTabListener { 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 @@ public class GitblitPanel extends JPanel implements CloseTabListener { 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); + 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 @@ public class GitblitPanel extends JPanel implements CloseTabListener { if (gitblit.allowAdmin()) { updateUsersTable(); + updateSettingsTable(); } else { // user does not have administrator privileges // hide admin repository buttons @@ -374,6 +457,11 @@ public class GitblitPanel extends JPanel implements CloseTabListener { usersModel.fireTableDataChanged(); } + private void updateSettingsTable() { + settingsModel.setSettings(gitblit.getSettings()); + settingsModel.fireTableDataChanged(); + } + private void filterRepositories(final String fragment) { if (StringUtils.isEmpty(fragment)) { repositoriesTable.setRowSorter(defaultRepositoriesSorter); @@ -415,6 +503,26 @@ public class GitblitPanel extends JPanel implements CloseTabListener { usersTable.setRowSorter(sorter); } + private void filterSettings(final String fragment) { + if (StringUtils.isEmpty(fragment)) { + settingsTable.setRowSorter(defaultSettingsSorter); + return; + } + RowFilter containsFilter = new RowFilter() { + public boolean include(Entry entry) { + for (int i = entry.getValueCount() - 1; i >= 0; i--) { + if (entry.getStringValue(i).toLowerCase().contains(fragment.toLowerCase())) { + return true; + } + } + return false; + } + }; + TableRowSorter sorter = new TableRowSorter(settingsModel); + sorter.setRowFilter(containsFilter); + settingsTable.setRowSorter(sorter); + } + private List getSelectedRepositories() { List repositories = new ArrayList(); for (int viewRow : repositoriesTable.getSelectedRows()) { @@ -572,6 +680,7 @@ public class GitblitPanel extends JPanel implements CloseTabListener { success &= gitblit.deleteRepository(repository); } if (success) { + gitblit.refreshRepositories(); gitblit.refreshUsers(); } return success; diff --git a/src/com/gitblit/client/HeaderPanel.java b/src/com/gitblit/client/HeaderPanel.java index b3953b39..0df29140 100644 --- a/src/com/gitblit/client/HeaderPanel.java +++ b/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,21 +25,27 @@ import java.awt.Paint; 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 { private static final long serialVersionUID = 1L; 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 @@ public class HeaderPanel extends JPanel { 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); } } diff --git a/src/com/gitblit/client/SettingsModel.java b/src/com/gitblit/client/SettingsModel.java new file mode 100644 index 00000000..2c7bff8d --- /dev/null +++ b/src/com/gitblit/client/SettingsModel.java @@ -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 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(); + } else { + keys = new ArrayList(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 Object.class regardless of columnIndex. + * + * @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; + } +} diff --git a/src/com/gitblit/client/Utils.java b/src/com/gitblit/client/Utils.java index 1ce6d7dc..c8375798 100644 --- a/src/com/gitblit/client/Utils.java +++ b/src/com/gitblit/client/Utils.java @@ -56,6 +56,7 @@ public class Utils { public static void showException(Component c, Throwable t) { // TODO show the unexpected exception + t.printStackTrace(); } public static void packColumns(JTable table, int margin) { diff --git a/src/com/gitblit/wicket/GitBlitWebApp.properties b/src/com/gitblit/wicket/GitBlitWebApp.properties index 9702e6cc..a811260a 100644 --- a/src/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/com/gitblit/wicket/GitBlitWebApp.properties @@ -155,4 +155,5 @@ gb.size = size gb.downloading = downloading gb.loading = loading gb.starting = starting -gb.general = general \ No newline at end of file +gb.general = general +gb.settings = settings \ No newline at end of file