/*
i-net software provides programming examples for illustration only, without warranty
either expressed or implied, including, but not limited to, the implied warranties
of merchantability and/or fitness for a particular purpose. This programming example
assumes that you are familiar with the programming language being demonstrated and
the tools used to create and debug procedures. i-net software support professionals
can help explain the functionality of a particular procedure, but they will not modify
these examples to provide added functionality or construct procedures to meet your
specific needs.
© i-net software 1998-2013
*/
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Linq;
using Inet.Viewer.Data;
using Inet.Viewer.Resources;
namespace Inet.Viewer.WinForms
{
///
/// A search panel containing a text field the search term and a list view for showing the results.
///
[ToolboxItem(true)]
[ToolboxBitmap(typeof(SearchPanel), "SearchPanel")]
public partial class SearchPanel : UserControl, ISearchResultReceiver
{
private const int TabCloseSelectedTop = 4;
private const int TabCloseSelectedRight = 20;
private const int TabCloseImageSize = 16;
///
/// Event is triggered when the user clicks the close button of the search panel.
///
[Description("Triggered when the user clicks the close button of the search panel"), Category("Action")]
public event EventHandler CloseClick;
private int currentPage;
private string currentQuery;
private IReportViewer reportViewer;
private IReportView currentReportView;
private SearchLoader currentSearchLoader;
private bool noResults;
private DataChanged dataChangedHandler;
private System.Drawing.Font boldFont;
///
/// Creates a new panel.
///
public SearchPanel()
{
InitializeComponent();
columnHeader1.TextAlign = HorizontalAlignment.Center;
dataChangedHandler = new DataChanged(reportView_DataChanged);
}
///
/// Sets the report viewer reference.
///
public IReportViewer ReportViewer
{
set
{
if (reportViewer != value)
{
if (reportViewer != null)
{
reportViewer.ViewChanged -= reportViewer_ViewChanged;
}
value.ViewChanged += reportViewer_ViewChanged;
reportViewer = value;
if (reportViewer != null)
{
reportViewer.ViewChanged += reportViewer_ViewChanged;
}
}
}
}
///
/// Called when the user selects a result row. Scrolls to the corresponding page in the ReportView.
///
///
///
private void listViewResults_SelectedIndexChanged(object sender, EventArgs e)
{
if (listViewResults.SelectedItems.Count == 1)
{
SearchResult result = (SearchResult)listViewResults.SelectedItems[0].Tag;
if (result != null)
{
reportViewer.CurrentReportView.Highlight(result.Chunks);
}
}
}
///
/// Called on key presses in query field. Starts a new search when the return key was pressed.
///
/// the sender
/// the event arguments
private void textBoxTerm_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Return)
{
StartNewSearch();
}
}
///
/// Called when the user clicks to search button. Starts a new search.
///
/// the sender
/// the event arguments
private void buttonStart_Click(object sender, EventArgs e)
{
StartNewSearch();
}
///
/// Starts a new search. Any previous results entries will be removed and the new search string is added to the history (combobox).
///
private void StartNewSearch()
{
currentQuery = comboBoxQuery.Text;
if (currentReportView != null)
{
currentReportView.DataChanged -= dataChangedHandler;
}
currentReportView = reportViewer.CurrentReportView;
if (currentReportView != null)
{
currentReportView.DataChanged += dataChangedHandler;
listViewResults.Items.Clear();
currentReportView.ClearSelection();
comboBoxQuery.Items.Remove(currentQuery);
comboBoxQuery.Items.Insert(0, currentQuery);
StartSearch(0);
}
}
///
/// Starts a search for the specified search page.
///
/// the search page as zero based index.
private void StartSearch(int page)
{
if (currentSearchLoader != null)
{
currentSearchLoader.Cancel();
}
listViewResults.Enabled = true;
currentSearchLoader = new SearchLoader(this, currentReportView.ReportData, currentQuery, page, SearchOption.None);
SearchProgress progress = new SearchProgress(currentReportView.ShowError, currentSearchLoader);
foreach(Progress p in reportViewer.ToolBar.SelectProgress(p=>p is SearchProgress).ToList()) {
p.Cancel();
}
reportViewer.ToolBar.AddProgress(progress);
progress.StartProgress();
}
///
/// Called when shown report tab in the viewer was changed. Disables the result box if the currently shown results
/// does not belong to the report tab. It also re-enables the box if the user switched back to the tab where the search
/// was performed.
///
/// the sender
/// the event arguments
private void reportViewer_ViewChanged(object sender, EventArgs e)
{
IReportView view = reportViewer.CurrentReportView;
listViewResults.Enabled = view == currentReportView && !noResults;
buttonStart.Enabled = view != null;
buttonContinue.Enabled = currentPage != -1 && view == currentReportView;
}
///
/// Called when the user clicks on "Continue Search". Starts the search of the next page.
///
/// the sender
/// the event arguments
private void buttonContinue_Click(object sender, EventArgs e)
{
StartSearch(currentPage + 1);
}
///
/// Called when the user clicks on the close button. Forwards this event to the CloseClick event of this instance.
///
/// the sender
/// the event arguments
private void OnCloseClicked(object sender, EventArgs data)
{
if (CloseClick != null)
{
CloseClick(this, data);
}
}
///
public void AddSearchResult(string pre, string result, string post, SearchChunk[] chunks)
{
SearchResult searchResult = new SearchResult(pre, result, post, chunks);
ListViewItem item = new ListViewItem();
item.UseItemStyleForSubItems = false;
item.SubItems.Add(new ListViewItem.ListViewSubItem(item, null));
item.Tag = searchResult;
listViewResults.BeginInvoke((MethodInvoker)delegate
{
bool first = listViewResults.Items.Count == 0;
if (!first && listViewResults.Items[listViewResults.Items.Count - 1].Tag == null)
{
listViewResults.Items.RemoveAt(listViewResults.Items.Count - 1);
}
else
{
listViewResults.Items.Add(item);
}
if (listViewResults.SelectedIndices.Count == 0 && searchResult.Page >= currentReportView.CurrentPage)
{
item.Selected = true;
listViewResults.FocusedItem = item;
listViewResults.Focus();
}
});
}
///
public void EndSearch(int page, long timestamp)
{
listViewResults.Invoke((MethodInvoker)delegate
{
currentSearchLoader = null;
if (listViewResults.Items.Count > 0 && listViewResults.Items[listViewResults.Items.Count - 1].Tag == null)
{
listViewResults.Items.RemoveAt(listViewResults.Items.Count - 1);
}
buttonContinue.Enabled = page != -1;
noResults = listViewResults.Items.Count == 0;
if (noResults)
{
ListViewItem item = new ListViewItem();
item.UseItemStyleForSubItems = false;
item.SubItems.Add(new ListViewItem.ListViewSubItem(item, strings.Search_NotFound));
listViewResults.Items.Add(item);
listViewResults.Enabled = false;
}
else if (page != -1)
{
ListViewItem item = new ListViewItem();
item.UseItemStyleForSubItems = false;
item.SubItems.Add(new ListViewItem.ListViewSubItem(item, string.Empty));
listViewResults.Items.Add(item);
}
});
currentPage = page;
}
///
public void CancelSearch()
{
}
private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
TabControl tabControl = (TabControl)sender;
TabPage page = tabControl.TabPages[e.Index];
e.Graphics.DrawImage(Images.closeButtonImage, e.Bounds.Right - TabCloseSelectedRight, e.Bounds.Top + TabCloseSelectedTop, Images.closeButtonImage.Width, Images.closeButtonImage.Height);
e.Graphics.DrawString(this.tabControl1.TabPages[e.Index].Text, e.Font, Brushes.Black, e.Bounds.Left + 4, e.Bounds.Top + 4);
e.DrawFocusRectangle();
}
private void tabControl1_MouseClick(object sender, MouseEventArgs e)
{
//Looping through all Tabs
for (int i = 0; i < this.tabControl1.TabPages.Count; i++)
{
TabPage page = this.tabControl1.TabPages[i];
Rectangle r = tabControl1.GetTabRect(i);
//Getting the position of the "x" mark of the selected Tab
Rectangle closeButton = new Rectangle(r.Right - TabCloseSelectedRight + 2, r.Top + TabCloseSelectedTop, TabCloseImageSize, TabCloseImageSize - 1);
if (closeButton.Contains(e.Location))
{
OnCloseClicked(this, new EventArgs());
break;
}
}
}
///
/// Focuses the input field of this panel.
///
internal void FocusInputField()
{
comboBoxQuery.Focus();
}
///
/// Called when the report data changed. Implementation clears any search result since they
/// may be invalid now.
///
///
///
private void reportView_DataChanged(object sender, long timestamp)
{
Invoke((MethodInvoker)delegate { listViewResults.Items.Clear(); });
}
///
/// A single result of a search.
///
private class SearchResult
{
private SearchChunk[] chunks;
public SearchResult(string pre, string result, string post, SearchChunk[] chunks)
{
PreText = "..." + pre;
Text = result;
PostText = post + "...";
this.chunks = chunks;
Page = chunks[0].Page;
}
///
/// Text before the found term.
///
public string PreText { get; set; }
///
/// The word including the found term.
///
public string Text { get; set; }
///
/// The text after the found term.
///
public string PostText { get; set; }
///
/// The report page index.
///
public int Page { get; set; }
public SearchChunk[] Chunks
{
get { return chunks; }
}
}
///
/// Draw event handler for list items.
///
///
///
private void listViewResults_DrawItem(object sender, DrawListViewItemEventArgs e)
{
e.DrawDefault = true;
}
///
/// Draw event handler for list sub items.
///
///
///
private void listViewResults_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
if (e.Item.Tag == null)
{
if (e.ColumnIndex == 1)
{
if (e.SubItem.Text == string.Empty && currentPage != -1)
{
e.SubItem.Text = strings.Search_Loading;
StartSearch(currentPage + 1);
}
e.Graphics.DrawString(e.SubItem.Text, DefaultFont, Brushes.DimGray, new PointF(e.Bounds.X + 20, e.Bounds.Y));
}
return;
}
e.DrawFocusRectangle(e.Bounds);
SearchResult searchResult = (SearchResult)e.Item.Tag;
switch (e.ColumnIndex)
{
case 0:
string text = searchResult.Page.ToString();
int w = (int)e.Graphics.MeasureString(text, DefaultFont).Width;
e.Graphics.DrawString(text, DefaultFont, Brushes.Gray, new PointF(e.Bounds.X + (e.Bounds.Width - w) / 2, e.Bounds.Y));
break;
case 1:
if (boldFont == null)
{
boldFont = new Font(DefaultFont, FontStyle.Bold);
}
PointF p = new PointF(e.Bounds.X, e.Bounds.Y);
e.Graphics.DrawString(searchResult.PreText, DefaultFont, Brushes.Black, p);
p.X += (int)e.Graphics.MeasureString(searchResult.PreText, DefaultFont).Width;
e.Graphics.DrawString(searchResult.Text, boldFont, Brushes.Black, p);
p.X += (int)e.Graphics.MeasureString(searchResult.Text, boldFont).Width + 2;
e.Graphics.DrawString(searchResult.PostText, DefaultFont, Brushes.Black, p);
break;
}
e.DrawDefault = false;
}
///
/// Draw event handler for list column headers.
///
///
///
private void listViewResults_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
e.DrawDefault = true;
}
}
}