/* 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; } } }