--- /dev/null
+/*\r
+ * Copyright 2011 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit.client;\r
+\r
+import java.awt.BorderLayout;\r
+import java.awt.FlowLayout;\r
+import java.awt.Insets;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.awt.event.MouseAdapter;\r
+import java.awt.event.MouseEvent;\r
+import java.awt.event.WindowAdapter;\r
+import java.awt.event.WindowEvent;\r
+import java.io.IOException;\r
+import java.util.List;\r
+\r
+import javax.swing.DefaultComboBoxModel;\r
+import javax.swing.ImageIcon;\r
+import javax.swing.JButton;\r
+import javax.swing.JComboBox;\r
+import javax.swing.JFrame;\r
+import javax.swing.JLabel;\r
+import javax.swing.JPanel;\r
+import javax.swing.JScrollPane;\r
+import javax.swing.JTable;\r
+import javax.swing.JTextField;\r
+import javax.swing.SwingWorker;\r
+import javax.swing.event.ListSelectionEvent;\r
+import javax.swing.event.ListSelectionListener;\r
+\r
+import com.gitblit.Constants;\r
+import com.gitblit.models.RepositoryModel;\r
+import com.gitblit.models.SyndicatedEntryModel;\r
+import com.gitblit.utils.StringUtils;\r
+\r
+/**\r
+ * The search dialog allows searching of a repository branch. This matches the\r
+ * search implementation of the site.\r
+ * \r
+ * @author James Moger\r
+ * \r
+ */\r
+public class SearchDialog extends JFrame {\r
+\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ private final GitblitClient gitblit;\r
+\r
+ private SyndicatedEntryTableModel tableModel;\r
+\r
+ private HeaderPanel header;\r
+\r
+ private JTable table;\r
+\r
+ private JComboBox repositorySelector;\r
+\r
+ private DefaultComboBoxModel branchChoices;\r
+\r
+ private JComboBox branchSelector;\r
+\r
+ private JComboBox searchTypeSelector;\r
+\r
+ private JTextField searchFragment;\r
+\r
+ private JComboBox maxHitsSelector;\r
+\r
+ public SearchDialog(GitblitClient gitblit) {\r
+ super();\r
+ this.gitblit = gitblit;\r
+ setTitle(Translation.get("gb.search"));\r
+ setIconImage(new ImageIcon(getClass().getResource("/gitblt-favicon.png")).getImage());\r
+ initialize();\r
+ setSize(900, 400);\r
+ }\r
+\r
+ private void initialize() {\r
+\r
+ final JButton search = new JButton(Translation.get("gb.search"));\r
+ search.addActionListener(new ActionListener() {\r
+ public void actionPerformed(ActionEvent e) {\r
+ search();\r
+ }\r
+ });\r
+\r
+ final JButton viewCommit = new JButton(Translation.get("gb.view"));\r
+ viewCommit.setEnabled(false);\r
+ viewCommit.addActionListener(new ActionListener() {\r
+ public void actionPerformed(ActionEvent e) {\r
+ viewCommit();\r
+ }\r
+ });\r
+\r
+ final JButton viewCommitDiff = new JButton(Translation.get("gb.commitdiff"));\r
+ viewCommitDiff.setEnabled(false);\r
+ viewCommitDiff.addActionListener(new ActionListener() {\r
+ public void actionPerformed(ActionEvent e) {\r
+ viewCommitDiff();\r
+ }\r
+ });\r
+\r
+ final JButton viewTree = new JButton(Translation.get("gb.tree"));\r
+ viewTree.setEnabled(false);\r
+ viewTree.addActionListener(new ActionListener() {\r
+ public void actionPerformed(ActionEvent e) {\r
+ viewTree();\r
+ }\r
+ });\r
+\r
+ JPanel controls = new JPanel(new FlowLayout(FlowLayout.CENTER, Utils.MARGIN, 0));\r
+ controls.add(viewCommit);\r
+ controls.add(viewCommitDiff);\r
+ controls.add(viewTree);\r
+\r
+ NameRenderer nameRenderer = new NameRenderer();\r
+ tableModel = new SyndicatedEntryTableModel();\r
+ header = new HeaderPanel(Translation.get("gb.search"), "search-icon.png");\r
+ table = Utils.newTable(tableModel, Utils.DATE_FORMAT);\r
+\r
+ String name = table.getColumnName(SyndicatedEntryTableModel.Columns.Author.ordinal());\r
+ table.setRowHeight(nameRenderer.getFont().getSize() + 8);\r
+ table.getColumn(name).setCellRenderer(nameRenderer);\r
+ name = table.getColumnName(SyndicatedEntryTableModel.Columns.Repository.ordinal());\r
+ table.getColumn(name).setCellRenderer(nameRenderer);\r
+\r
+ name = table.getColumnName(SyndicatedEntryTableModel.Columns.Branch.ordinal());\r
+ table.getColumn(name).setCellRenderer(new BranchRenderer());\r
+\r
+ name = table.getColumnName(SyndicatedEntryTableModel.Columns.Message.ordinal());\r
+ table.getColumn(name).setCellRenderer(new MessageRenderer());\r
+\r
+ table.addMouseListener(new MouseAdapter() {\r
+ public void mouseClicked(MouseEvent e) {\r
+ if (e.getClickCount() == 2) {\r
+ if (e.isControlDown()) {\r
+ viewCommitDiff();\r
+ } else {\r
+ viewCommit();\r
+ }\r
+ }\r
+ }\r
+ });\r
+\r
+ table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {\r
+ @Override\r
+ public void valueChanged(ListSelectionEvent e) {\r
+ if (e.getValueIsAdjusting()) {\r
+ return;\r
+ }\r
+ boolean singleSelection = table.getSelectedRowCount() == 1;\r
+ viewCommit.setEnabled(singleSelection);\r
+ viewCommitDiff.setEnabled(singleSelection);\r
+ viewTree.setEnabled(singleSelection);\r
+ }\r
+ });\r
+\r
+ repositorySelector = new JComboBox(gitblit.getRepositories().toArray());\r
+ repositorySelector.setRenderer(nameRenderer);\r
+ repositorySelector.setForeground(nameRenderer.getForeground());\r
+ repositorySelector.addActionListener(new ActionListener() {\r
+ public void actionPerformed(ActionEvent event) {\r
+ // repopulate the branch list based on repository selection\r
+ // preserve branch selection, if possible\r
+ String selectedBranch = null;\r
+ if (branchSelector.getSelectedIndex() > -1) {\r
+ selectedBranch = branchSelector.getSelectedItem().toString();\r
+ }\r
+ updateBranches();\r
+ if (selectedBranch != null) {\r
+ if (branchChoices.getIndexOf(selectedBranch) > -1) {\r
+ branchChoices.setSelectedItem(selectedBranch);\r
+ }\r
+ }\r
+ }\r
+ });\r
+\r
+ branchChoices = new DefaultComboBoxModel();\r
+ branchSelector = new JComboBox(branchChoices);\r
+ branchSelector.setRenderer(new BranchRenderer());\r
+\r
+ searchTypeSelector = new JComboBox(Constants.SearchType.values());\r
+ searchTypeSelector.setSelectedItem(Constants.SearchType.COMMIT);\r
+\r
+ maxHitsSelector = new JComboBox(new Integer[] { 25, 50, 75, 100 });\r
+ maxHitsSelector.setSelectedIndex(-1);\r
+\r
+ searchFragment = new JTextField(25);\r
+ searchFragment.addActionListener(new ActionListener() {\r
+ public void actionPerformed(ActionEvent event) {\r
+ search();\r
+ }\r
+ });\r
+\r
+ JPanel northControls = new JPanel(new FlowLayout(FlowLayout.LEFT, Utils.MARGIN, 0));\r
+ northControls.add(new JLabel(Translation.get("gb.repository")));\r
+ northControls.add(repositorySelector);\r
+ northControls.add(new JLabel(Translation.get("gb.branch")));\r
+ northControls.add(branchSelector);\r
+ northControls.add(new JLabel(Translation.get("gb.type")));\r
+ northControls.add(searchTypeSelector);\r
+ northControls.add(new JLabel(Translation.get("gb.maxHits")));\r
+ northControls.add(maxHitsSelector);\r
+ northControls.add(searchFragment);\r
+ northControls.add(search);\r
+\r
+ JPanel northPanel = new JPanel(new BorderLayout(0, Utils.MARGIN));\r
+ northPanel.add(header, BorderLayout.NORTH);\r
+ northPanel.add(northControls, BorderLayout.CENTER);\r
+\r
+ JPanel contentPanel = new JPanel() {\r
+\r
+ private static final long serialVersionUID = 1L;\r
+\r
+ @Override\r
+ public Insets getInsets() {\r
+ return Utils.INSETS;\r
+ }\r
+ };\r
+ contentPanel.setLayout(new BorderLayout(Utils.MARGIN, Utils.MARGIN));\r
+ contentPanel.add(northPanel, BorderLayout.NORTH);\r
+ contentPanel.add(new JScrollPane(table), BorderLayout.CENTER);\r
+ contentPanel.add(controls, BorderLayout.SOUTH);\r
+ setLayout(new BorderLayout());\r
+ add(contentPanel, BorderLayout.CENTER);\r
+ addWindowListener(new WindowAdapter() {\r
+ @Override\r
+ public void windowOpened(WindowEvent event) {\r
+ searchFragment.requestFocus();\r
+ }\r
+\r
+ @Override\r
+ public void windowActivated(WindowEvent event) {\r
+ searchFragment.requestFocus();\r
+ }\r
+ });\r
+ }\r
+\r
+ public void selectRepository(RepositoryModel repository) {\r
+ repositorySelector.setSelectedItem(repository);\r
+ }\r
+\r
+ private void updateBranches() {\r
+ String repository = null;\r
+ if (repositorySelector.getSelectedIndex() > -1) {\r
+ repository = repositorySelector.getSelectedItem().toString();\r
+ }\r
+ List<String> branches = gitblit.getBranches(repository);\r
+ branchChoices.removeAllElements();\r
+ for (String branch : branches) {\r
+ branchChoices.addElement(branch);\r
+ }\r
+ }\r
+\r
+ protected void search() {\r
+ final String repository = repositorySelector.getSelectedItem().toString();\r
+ final String branch = branchSelector.getSelectedIndex() > -1 ? branchSelector\r
+ .getSelectedItem().toString() : null;\r
+ final Constants.SearchType searchType = (Constants.SearchType) searchTypeSelector\r
+ .getSelectedItem();\r
+ final String fragment = searchFragment.getText();\r
+ final int maxEntryCount = maxHitsSelector.getSelectedIndex() > -1 ? ((Integer) maxHitsSelector\r
+ .getSelectedItem()) : -1;\r
+ if (StringUtils.isEmpty(fragment)) {\r
+ return;\r
+ }\r
+ SwingWorker<List<SyndicatedEntryModel>, Void> worker = new SwingWorker<List<SyndicatedEntryModel>, Void>() {\r
+ @Override\r
+ protected List<SyndicatedEntryModel> doInBackground() throws IOException {\r
+ return gitblit.search(repository, branch, fragment, searchType, maxEntryCount);\r
+ }\r
+\r
+ @Override\r
+ protected void done() {\r
+ try {\r
+ List<SyndicatedEntryModel> results = get();\r
+ updateTable(true, fragment, results);\r
+ } catch (Throwable t) {\r
+ Utils.showException(SearchDialog.this, t);\r
+ }\r
+ }\r
+ };\r
+ worker.execute();\r
+ }\r
+\r
+ protected void updateTable(boolean pack, String fragment, List<SyndicatedEntryModel> entries) {\r
+ tableModel.entries.clear();\r
+ tableModel.entries.addAll(entries);\r
+ tableModel.fireTableDataChanged();\r
+ setTitle(Translation.get("gb.search") + ": " + fragment + " (" + entries.size() + ")");\r
+ header.setText(getTitle());\r
+ if (pack) {\r
+ Utils.packColumns(table, Utils.MARGIN);\r
+ }\r
+ }\r
+\r
+ protected SyndicatedEntryModel getSelectedSyndicatedEntry() {\r
+ int viewRow = table.getSelectedRow();\r
+ int modelRow = table.convertRowIndexToModel(viewRow);\r
+ SyndicatedEntryModel entry = tableModel.get(modelRow);\r
+ return entry;\r
+ }\r
+\r
+ protected void viewCommit() {\r
+ SyndicatedEntryModel entry = getSelectedSyndicatedEntry();\r
+ Utils.browse(entry.link);\r
+ }\r
+\r
+ protected void viewCommitDiff() {\r
+ SyndicatedEntryModel entry = getSelectedSyndicatedEntry();\r
+ Utils.browse(entry.link.replace("/commit/", "/commitdiff/"));\r
+ }\r
+\r
+ protected void viewTree() {\r
+ SyndicatedEntryModel entry = getSelectedSyndicatedEntry();\r
+ Utils.browse(entry.link.replace("/commit/", "/tree/"));\r
+ }\r
+}\r