///
/// Copyright © 2003-2008 JetBrains s.r.o.
/// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder).
///
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using JetBrains.Interop.WinApi;
using JetBrains.Omea.Base;
using JetBrains.Omea.FiltersManagement;
using JetBrains.Omea.GUIControls.CommandBar;
using JetBrains.Omea.GUIControls.CustomViews;
using JetBrains.Omea.OpenAPI;
using JetBrains.Omea.ResourceTools;
using JetBrains.UI.Components.ImageListButton;
using JetBrains.UI.Interop;
namespace JetBrains.Omea.GUIControls
{
///
/// Summary description for SearchCtrl.
///
public class SearchCtrl : UserControl, ICommandBar
{
#region Attributes
const int _nRightMargin = 2;
private const string _ChooserTooltip = "Select where to search";
private const string _NotReadyErrorMessage = "Text index is not built or loaded yet";
private const string _NotReadyErrorCaption = "Search query failed";
/// Minimum allowed width of the combobox.
protected static readonly int c_nMinComboWidth = 100;
/// Gap between the controls.
protected static readonly int c_nGap = 5;
private readonly List _storedQueries = new List();
private IContainer components;
private JetLinkLabel _labelTitle;
private SelfDrawnPanelWithBorder _panelChoosingButtons;
private ImageListButton _btnProvider;
private ImageListButton _btnProviderChooser;
private ACMarginableComboBox _searchQueryCombo;
private ImageListButton _btnSearch;
private JetLinkLabel _labelAdvanced;
private ToolTip _tipReason;
private static AdvancedSearchForm AdvSForm;
private static string CurrentSearchText = string.Empty;
private ISearchProvider _currentProvider;
private ContextMenu _menuProviders;
private MenuItem _currentProviderItem;
private ArrayList _searchProviders;
/// The command bar site.
protected ICommandBarSite _site;
/// The grip.
protected Grip _grip;
/// Scaling factor for the component.
protected SizeF _sizeScale = new SizeF( 1, 1 );
#endregion Attributes
#region Construction
public SearchCtrl()
{
InitializeComponent();
SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.CacheText |
ControlStyles.ContainerControl | ControlStyles.ResizeRedraw |
ControlStyles.Selectable | ControlStyles.UserPaint | ControlStyles.Opaque, true );
// Load the size (change the control width only)
int nNewWidth = Core.SettingStore.ReadInt( "SearchBar", "CustomWidth", OptimalSize.Width );
nNewWidth = nNewWidth >= MinSize.Width ? nNewWidth : MinSize.Width;
Size = new Size( nNewWidth, Size.Height );
}
private void InitializeSearchProviders()
{
_currentProvider = Core.TextIndexManager.CurrentSearchProvider;
_menuProviders = new ContextMenu();
_searchProviders = new ArrayList();
string[] groups = Core.TextIndexManager.GetSearchProviderGroups();
foreach( string group in groups )
{
EventHandler eh = onProviderSelected;
MeasureItemEventHandler mieh = ProviderMenuItem.mi_MeasureItem;
DrawItemEventHandler dieh = ProviderMenuItem.mi_DrawItem;
ISearchProvider[] providers = Core.TextIndexManager.GetSearchProvidersInGroup( group );
//-------------------------------------------------------------
// Check this until we manage to delete empty groups when
// providers are delete on the fly.
//-------------------------------------------------------------
if( providers.Length > 0 )
{
//---------------------------------------------------------
// Add named group only in the case of valid name. Empty name
// is most common used for miscellaneous minor search
// providers just for the possibility not to construct name
// "Others" or smth like this.
//---------------------------------------------------------
if( group.Length > 0 )
{
ProvidersHeaderMenuItem pmi = new ProvidersHeaderMenuItem( group );
pmi.OwnerDraw = true;
pmi.Enabled = false;
pmi.MeasureItem += ProvidersHeaderMenuItem.mi_MeasureItem;
pmi.DrawItem += ProvidersHeaderMenuItem.mi_DrawItem;
_menuProviders.MenuItems.Add( pmi );
}
foreach( ISearchProvider provider in providers )
{
MenuItem mi = new ProviderMenuItem( provider, eh );
mi.RadioCheck = true;
mi.OwnerDraw = true;
mi.MeasureItem += mieh;
mi.DrawItem += dieh;
_menuProviders.MenuItems.Add( mi );
_searchProviders.Add( provider );
if( _currentProvider == provider )
{
_btnProvider.AddIcon( provider.Icon, ImageListButton.ButtonState.Normal );
_currentProviderItem = mi;
mi.Checked = true;
}
}
}
// Different groups are delimited by the dash line.
if( group != groups[ groups.Length - 1 ] )
_menuProviders.MenuItems.Add( new MenuItem( "-" ) );
}
ShowProviderNameTip();
}
///
/// Clean up any resources being used.
///
protected override void Dispose( bool disposing )
{
if( disposing )
{
if( components != null )
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#endregion
[DefaultValue( null )]
public ColorScheme ColorScheme { get; set; }
#region Visual Init
private void InitializeComponent()
{
components = new Container();
_labelAdvanced = new JetLinkLabel();
_labelTitle = new JetLinkLabel();
_btnProvider = new ImageListButton();
_searchQueryCombo = new ACMarginableComboBox();
_btnSearch = new ImageListButton();
_btnProviderChooser = new ImageListButton ();
_panelChoosingButtons = new SelfDrawnPanelWithBorder();
_tipReason = new ToolTip( components );
BackColor = SystemColors.Control;
SuspendLayout();
//
// _btnProviderChooser
//
_btnProviderChooser.Location = new Point(16, 1);
_btnProviderChooser.Name = "_btnProviderChooser";
_btnProviderChooser.PressedImageIndex = -1;
_btnProviderChooser.Size = new Size( 16, 16 );
_btnProviderChooser.Click += _btnProviderChooser_Click;
_btnProviderChooser.BackColor = Color.Transparent;
_btnProviderChooser.AddIcon(Utils.TryGetEmbeddedResourceIconFromAssembly("GUIControls", "GUIControls.Icons.chooser.ico"), ImageListButton.ButtonState.Normal);
//
// _panelChoosingButtons
//
_panelChoosingButtons.Location = new Point(90, 8);
_panelChoosingButtons.Size = new Size(15, 17);
_panelChoosingButtons.BackColor = Color.Transparent;
_panelChoosingButtons.ForeColor = Color.Transparent;
// _panelChoosingButtons.Controls.Add(_btnProviderChooser);
_panelChoosingButtons.Paint += _panelChoosingButtons_Paint;
_panelChoosingButtons.EnabledChanged += _panelChoosingButtons_EnabledChanged;
//
// _labelTitle
//
_labelTitle.Font = new Font( "Tahoma", 8.25F, FontStyle.Bold, GraphicsUnit.Point, 204 );
_labelTitle.Location = new Point( 8, 3 );
_labelTitle.Name = "_labelTitle";
_labelTitle.Size = new Size( 44, 16 );
_labelTitle.TabStop = false;
_labelTitle.Text = "Search";
_labelTitle.BackColor = BackColor;
_labelTitle.ForeColor = SystemColors.ControlText;
_labelTitle.ClickableLink = false;
//
// _btnProvider
//
_btnProvider.Location = new Point(0, 0);
_btnProvider.Name = "_btnProvider";
_btnProvider.PressedImageIndex = -1;
_btnProvider.Size = new Size(16, 16);
_btnProvider.Padding = new Padding( 0 );
_btnProvider.AutoSize = false;
_btnProvider.BackColor = BackColor;
_btnProvider.Click += _btnProviderChooser_Click;
//
// _searchQueryCombo
//
_searchQueryCombo.DropDownWidth = 200;
_searchQueryCombo.Location = new Point( 62, 0 );
_searchQueryCombo.Name = "_searchQueryCombo";
_searchQueryCombo.Size = new Size( 170, 24 );
_searchQueryCombo.TabIndex = 2;
_searchQueryCombo.KeyDown += SearchQuery_KeyDown;
_searchQueryCombo.KeyPress += _searchQueryCombo_KeyPress;
_searchQueryCombo.SelectedIndexChanged += _searchQueryCombo_SelectedIndexChanged;
_searchQueryCombo.Leave += _searchQueryCombo_Leave;
_searchQueryCombo.Enter += _searchQueryCombo_Enter;
_searchQueryCombo.GotFocus += _searchQueryCombo_GotFocus;
_searchQueryCombo.LostFocus += _searchQueryCombo_GotFocus;
//
// _btnSearch
//
_btnSearch.Location = new Point( 248, 0 );
_btnSearch.Name = "_btnSearch";
_btnSearch.PressedImageIndex = -1;
_btnSearch.Size = new Size( 37, 22 );
_btnSearch.TabIndex = 3;
_btnSearch.Click += OnClick;
_btnSearch.BackColor = BackColor;
_btnSearch.AddIcon( Utils.TryGetEmbeddedResourceIconFromAssembly( "GUIControls", "GUIControls.Icons.SearchControl.Go.Normal.ico" ), ImageListButton.ButtonState.Normal);
_btnSearch.AddIcon( Utils.TryGetEmbeddedResourceIconFromAssembly( "GUIControls", "GUIControls.Icons.SearchControl.Go.Hot.ico" ), ImageListButton.ButtonState.Hot);
_btnSearch.AddIcon( Utils.TryGetEmbeddedResourceIconFromAssembly( "GUIControls", "GUIControls.Icons.SearchControl.Go.Disabled.ico" ), ImageListButton.ButtonState.Disabled);
//
// _lblAdvanced
//
_labelAdvanced.Cursor = Cursors.Hand;
_labelAdvanced.ForeColor = Color.FromArgb( 70, 70, 211 );
_labelAdvanced.BackColor = BackColor;
_labelAdvanced.Name = "_labelAdvanced";
_labelAdvanced.TabIndex = 4;
_labelAdvanced.Text = "Advanced...";
_labelAdvanced.Click += AdvancedSearchLinkClicked;
//
// Grip
//
_grip = new Grip( this );
//
// _tipReason
//
_tipReason.ShowAlways = true;
//
// SearchCtrl
//
Controls.Add( _labelAdvanced );
Controls.Add( _labelTitle );
// Controls.Add( _panelChoosingButtons );
Controls.Add( _searchQueryCombo );
Controls.Add( _btnSearch );
Controls.Add( _btnProvider );
Font = new Font( "Tahoma", 8.25F, FontStyle.Regular, GraphicsUnit.Point, 204 );
Name = "SearchCtrl";
Size = OptimalSize;
ResumeLayout( false );
_searchQueryCombo.Attach(_btnProvider);
}
#endregion
#region OnLeave/OnEnter
protected override void OnEnter( EventArgs e )
{
base.OnEnter( e );
// Set the highlighted background color
BackColor = SystemColors.ControlLight;
_labelTitle.BackColor = BackColor;
_labelAdvanced.BackColor = BackColor;
_btnSearch.BackColor = BackColor;
HideProviderNameTip();
Invalidate( true );
}
protected override void OnLeave( EventArgs e )
{
base.OnLeave( e );
// Set the non-highlighted background color
BackColor = SystemColors.Control;
_labelTitle.BackColor = BackColor;
_labelAdvanced.BackColor = BackColor;
_btnSearch.BackColor = BackColor;
ShowProviderNameTip();
Invalidate( true );
}
#endregion OnLeave/OnEnter
#region OnGotFocus
private void _searchQueryCombo_GotFocus(object sender, EventArgs e)
{
if( _searchQueryCombo.Focused )
HideProviderNameTip();
else
ShowProviderNameTip();
}
#endregion OnGotFocus
#region OnPaint
protected override void OnPaint( PaintEventArgs e )
{ // no base class call — no excessive flicker, all is hanlded here
// Main Background
e.Graphics.FillRectangle( new SolidBrush( BackColor ), RectInsideBorder );
// Border
/*
Borders drawing sequence:
# dark-dark
@ dark
L lightlight
@ @@@@@@@@@@@@@@-1-@@@@@@@@@@@@@@@@@L
@ L
@ L LLLLLLLLLLL-5-LLLLLLLLLLLLLL# L
@ L # L
| | | |
2 6 8 4
| | | |
@ L L
@ #############-7-############### L
@
LLLLLLLLLLLLLLLL-3-LLLLLLLLLLLLLLLLLL
*/
Rectangle rc = ClientRectangle;
// Outer
e.Graphics.DrawLine( SystemPens.ControlDark, rc.Left + 1, rc.Top + 0, rc.Right - 2, rc.Top + 0 ); // 1
e.Graphics.DrawLine( SystemPens.ControlDark, rc.Left + 0, rc.Top + 0, rc.Left + 0, rc.Bottom - 2 ); // 2
e.Graphics.DrawLine( SystemPens.ControlLightLight, rc.Left + 0, rc.Bottom - 1, rc.Right - 1, rc.Bottom - 1 ); // 3
e.Graphics.DrawLine( SystemPens.ControlLightLight, rc.Right - 1, rc.Top + 0, rc.Right - 1, rc.Bottom - 2 ); // 4
// Inner
e.Graphics.DrawLine( SystemPens.ControlLightLight, rc.Left + 2, rc.Top + 1, rc.Right - 3, rc.Top + 1 ); // 5
e.Graphics.DrawLine( SystemPens.ControlLightLight, rc.Left + 1, rc.Top + 1, rc.Left + 1, rc.Bottom - 3 ); // 6
e.Graphics.DrawLine( SystemPens.ControlDarkDark, rc.Left + 1, rc.Bottom - 2, rc.Right - 2, rc.Bottom - 2 ); // 7
e.Graphics.DrawLine( SystemPens.ControlDarkDark, rc.Right - 2, rc.Top + 1, rc.Right - 2, rc.Bottom - 3 ); // 8
// Grip
_grip.OnPaint( e.Graphics );
}
private void _panelChoosingButtons_Paint(object sender, PaintEventArgs e)
{
Rectangle rc = _panelChoosingButtons.ClientRectangle;
Brush br = new SolidBrush( Color.Transparent );
rc.X += 1;
rc.Y += 1;
rc.Height -= 2;
e.Graphics.FillRectangle( br, rc );
}
#endregion OnPaint
#region OnLayout
protected override void OnLayout( LayoutEventArgs levent )
{ // no base class call — no excessive layouting, all is handled here
using( new LayoutSuspender( _labelAdvanced ) )
using( new LayoutSuspender( _labelTitle ) )
using( new LayoutSuspender( _searchQueryCombo ) )
using( new LayoutSuspender( _btnSearch ) )
{
// Take the grip into account
Rectangle rectInsideGrip = _grip.OnLayout( RectInsideBorder );
int nLeftMargin = rectInsideGrip.Left + 3; // Actually, that's all we have to do about the grip
int nAvailWidth = Width;
nAvailWidth -= nLeftMargin + _nRightMargin; // Margins
// If we have too small width, start dropping the unnecessary controls
// Order: title, advanced, go, combo
bool bTakeTitle = true;
bool bTakeCombo = true;
bool bTakeGo = true;
bool bTakeAdvanced = true;
int nComboWidth = nAvailWidth - _labelTitle.Width - /*_btnSearch.Width - */_labelAdvanced.Width + c_nGap * 3;
// Drop title?
if( nComboWidth < c_nMinComboWidth )
{
bTakeTitle = false;
nComboWidth += _labelTitle.Width + c_nGap;
}
// Drop Advanced?
if( nComboWidth < c_nMinComboWidth )
{
bTakeAdvanced = false;
nComboWidth += _labelAdvanced.Width + c_nGap;
}
// Drop Go?
if( nComboWidth < c_nMinComboWidth )
{
bTakeGo = false;
nComboWidth += _btnSearch.Width + c_nGap;
}
// Drop combo?
if( nComboWidth < c_nMinComboWidth )
bTakeCombo = false;
// Now, position the controls
int nLeft = nLeftMargin; // Current occupied space on the left
int nRight = _nRightMargin; // Current occupied space on the right
if( bTakeTitle )
{
_labelTitle.Visible = true;
_labelTitle.Location = new Point( nLeft, (Height - _labelTitle.Height) / 2 );
nLeft += _labelTitle.Width + c_nGap;
}
else
_labelTitle.Visible = false;
if( bTakeAdvanced )
{
_labelAdvanced.Visible = true;
_labelAdvanced.Location = new Point( Width - nRight - _labelAdvanced.Width, (Height - _labelAdvanced.Height) / 2 );
nRight += _labelAdvanced.Width + c_nGap;
}
else
_labelAdvanced.Visible = false;
if( bTakeGo )
{
_btnSearch.Visible = true;
_btnSearch.Location = new Point( Width - nRight - _btnSearch.Width, (Height - _btnSearch.Height) / 2 );
nRight += _btnSearch.Width + c_nGap;
}
else
_btnSearch.Visible = false;
if( bTakeCombo )
{
_searchQueryCombo.Visible = true;
_searchQueryCombo.Location = new Point( nLeft, (Height - _searchQueryCombo.Height) / 2 );
_searchQueryCombo.Width = Width - nRight - nLeft;
}
else
_searchQueryCombo.Visible = false;
}
// Apply the visual changes
Invalidate( false );
}
///
/// Scales the control.
///
protected override void ScaleCore( float dx, float dy )
{
_sizeScale = new SizeF( dx, dy );
base.ScaleCore( dx, dy );
}
///
/// Layout the controls.
///
///
///
/// — (grip) — [#TITLE#] [#COMBO#] [#GO#] [#ADVANCED#] —
/// 3px 3px 3px auto max-avail auto? auto 2px
///
/// Total width is adjusted to occupy all the available control width.
/// All the control widths are constant but for the COMBO, which widens as needed.
/// Height is constant, controls are v-centered in the available space.
///
protected Rectangle RectInsideBorder
{
get
{
Rectangle rc = ClientRectangle;
rc.Inflate( -2, -2 );
return rc;
}
}
#endregion OnLayout
#region Static Operations
// Static method is called exclusively from action "Refine this search"
// because in that source point (GUI Controls) we have no access to the
// Search control of the MainWindow.
public static void ShowAdvancedSearchDialog( IResource refinedView )
{
if( AdvSForm != null && !AdvSForm.IsDisposed )
{
AdvSForm.Close();
}
AdvSForm = new AdvancedSearchForm( refinedView );
AdvSForm.Show();
}
#endregion
#region Query Processing
#region Load/Save Queries in Ini
private void LoadSavedQueries()
{
int QueriesNumber = Core.SettingStore.ReadInt( "Search", "QueriesNumber", 0 );
if( QueriesNumber > 0 )
{
_storedQueries.Clear();
QueriesNumber = Math.Min( QueriesNumber, 10 );
_searchQueryCombo.BeginUpdate();
for( int i = 0; i < QueriesNumber; i++ )
{
string Query = Core.SettingStore.ReadString( "Search", "Query" + i );
if( Query.Length > 0 )
{
_searchQueryCombo.Items.Add( Query );
_storedQueries.Add( Query );
}
}
_searchQueryCombo.EndUpdate();
}
}
private void UpdateStoredQueriesList( string searchText )
{
int Index = _storedQueries.IndexOf( searchText );
if( Index != -1 )
_storedQueries.RemoveAt( Index );
else
{
_searchQueryCombo.BeginUpdate();
_searchQueryCombo.Items.Insert( 0, searchText );
_searchQueryCombo.EndUpdate();
}
_storedQueries.Insert( 0, searchText );
int QueriesNumber = Math.Min( _storedQueries.Count, 10 );
Core.SettingStore.WriteInt( "Search", "QueriesNumber", QueriesNumber );
for( int i = 0; i < QueriesNumber; i++ )
Core.SettingStore.WriteString( "Search", "Query" + i, _storedQueries[ i ] );
}
#endregion Load/Save Queries in Ini
private void OnIndexConstructionComplete( object sender, EventArgs e )
{
Core.TextIndexManager.IndexLoaded -= OnIndexConstructionComplete;
// forbid calling the processing during shutdown
if( Core.State == CoreState.Running )
{
Core.UIManager.QueueUIJob( new MethodInvoker( EnableCtrl ) );
}
}
private void AdvancedSearchLinkClicked( object sender, EventArgs e )
{
// forbid calling the processing during initialization
if( Core.State == CoreState.Running )
ShowAdvancedSearchDialog();
}
private void OnClick( object sender, EventArgs e )
{
if( Core.TextIndexManager == null || !Core.TextIndexManager.IsIndexPresent() )
{
MessageBox.Show( Core.MainWindow, _NotReadyErrorMessage, _NotReadyErrorCaption,
MessageBoxButtons.OK, MessageBoxIcon.Warning );
}
else
// forbid calling the processing during initialization
if( Core.State == CoreState.Running )
{
// Check also for mysterious case when the text value of standard
// control's property is null.
string searchText = _searchQueryCombo.Text ?? string.Empty;
searchText = searchText.Trim();
Trace.WriteLine( "Performing full-scale search using query: [" + searchText + "]" );
PerformSearchAction( searchText );
Trace.WriteLine( "Full-scale search done" );
Core.ResourceBrowser.FocusResourceList();
}
}
private void PerformSearchAction( string searchText )
{
if( searchText.Length > 0 )
{
UpdateStoredQueriesList( searchText );
Cursor.Current = Cursors.WaitCursor;
EnableControls( false );
SetTooltip( "Query is processed now" );
_currentProvider.ProcessQuery( searchText );
EnableControls( true );
SetTooltip();
Cursor.Current = Cursors.Default;
}
}
public static void CreateSearchView( string query, bool showContexts )
{
//-----------------------------------------------------------------
// Avoid perform any UI (and other, generally) work if we are
// shutting down - some components (like DefaultViewPane) may
// already be disposed.
//-----------------------------------------------------------------
if( Core.State != CoreState.Running )
return;
//-----------------------------------------------------------------
// Extract Search Extension subphrases, extract them out of the
// query and convert them into the list of conditions.
//-----------------------------------------------------------------
int anchorPos;
string[] resTypes = null;
bool parseSuccessful = false;
ArrayList conditions = new ArrayList();
do
{
string anchor;
FindSearchExtension( query, out anchor, out anchorPos );
if( anchorPos != -1 )
parseSuccessful = ParseSearchExtension( anchor, anchorPos, ref query, out resTypes, conditions );
}
while(( anchorPos != -1 ) && parseSuccessful );
//-----------------------------------------------------------------
// Create condition from the query
//-----------------------------------------------------------------
IFilterRegistry fMgr = Core.FilterRegistry;
IResource queryCondition = ((FilterRegistry) fMgr).CreateStandardConditionAux( null, query, ConditionOp.QueryMatch );
FilterRegistry.ReferCondition2Template( queryCondition, fMgr.Std.BodyMatchesSearchQueryXName );
conditions.Add( queryCondition );
//-----------------------------------------------------------------
bool showDelItems = Core.SettingStore.ReadBool( "Search", "ShowDeletedItems", true );
IResource[] condsList = (IResource[]) conditions.ToArray( typeof(IResource) );
IResource view = Core.ResourceStore.FindUniqueResource( FilterManagerProps.ViewResName, "DeepName", Core.FilterRegistry.ViewNameForSearchResults );
if( view != null )
fMgr.ReregisterView( view, fMgr.ViewNameForSearchResults, resTypes, condsList, null );
else
view = fMgr.RegisterView( fMgr.ViewNameForSearchResults, resTypes, condsList, null );
Core.FilterRegistry.SetVisibleInAllTabs( view );
//-----------------------------------------------------------------
// Set additional properties characteristic only for "Search Results"
// view.
//-----------------------------------------------------------------
ResourceProxy proxy = new ResourceProxy( view );
proxy.BeginUpdate();
proxy.SetProp( Core.Props.Name, AdvancedSearchForm.SearchViewPrefix + query );
proxy.SetProp( "_DisplayName", AdvancedSearchForm.SearchViewPrefix + query );
proxy.SetProp( Core.Props.ShowDeletedItems, showDelItems );
proxy.SetProp( "ShowContexts", showContexts );
proxy.SetProp( "ForceExec", true );
if( Core.SettingStore.ReadBool( "Search", "AutoSwitchToResults", true ) )
proxy.SetProp( "RunToTabIfSingleTyped", true );
else
proxy.DeleteProp( "RunToTabIfSingleTyped" );
proxy.EndUpdate();
//-----------------------------------------------------------------
// Add new view to the panel
// Some steps to specify the correct user-ordering for the new view.
//-----------------------------------------------------------------
Core.ResourceTreeManager.LinkToResourceRoot( view, int.MinValue );
new UserResourceOrder( Core.ResourceTreeManager.ResourceTreeRoot ).Insert( 0, new[] {view.Id}, false, null );
//-----------------------------------------------------------------
// If we still in the Running mode we can do some UI work...
//-----------------------------------------------------------------
if( Core.State == CoreState.Running )
{
Core.UIManager.BeginUpdateSidebar();
Core.LeftSidebar.ActivateViewPane( StandardViewPanes.ViewsCategories );
Core.UIManager.EndUpdateSidebar();
Core.LeftSidebar.DefaultViewPane.SelectResource( view );
}
}
#region SearchExtensions parsing
private static void FindSearchExtension( string query, out string prep, out int prepPosition )
{
prepPosition = -1;
prep = null;
string[] preps = Core.SearchQueryExtensions.GetAllAnchors();
for( int i = 0; i < preps.Length; i++ )
{
int pos = query.LastIndexOf( " " + preps[ i ] + " " );
if( pos > prepPosition )
{
prep = preps[ i ];
prepPosition = pos;
}
}
}
private static bool ParseSearchExtension( string prep, int prepPosition, ref string query,
out string[] resTypes, IList conditions )
{
string savedQuery = query;
ArrayList types = new ArrayList();
IResource condition = null;
string tokens = query.Substring( prepPosition + prep.Length + 2 );
query = query.Substring( 0, prepPosition );
resTypes = null;
string[] anchors = tokens.Split( ' ' );
for( int i = 0; i < anchors.Length; i++ )
{
string resType = Core.SearchQueryExtensions.GetResourceTypeRestriction( prep, anchors[ i ] );
condition = Core.SearchQueryExtensions.GetSingleTokenRestriction( prep, anchors[ i ] );
if( resType != null )
{
types.Add( resType );
}
else
if( condition != null )
{
conditions.Add( condition );
}
else
{
condition = Core.SearchQueryExtensions.GetMatchingFreestyleRestriction( prep, tokens );
if( condition != null )
conditions.Add( condition );
else
{
// Restore the query to the original text in the case when
// no alternative matched.
query = savedQuery;
}
break;
}
}
if( types.Count > 0 )
resTypes = (string[]) types.ToArray( typeof( string ));
return (resTypes != null) || (condition != null);
}
#endregion SearchExtensions parsing
#endregion Query Processing
#region SearchQuery Combobox Events
private void SearchQuery_KeyDown( object sender, KeyEventArgs e )
{
#region Preconditions
if( Core.ActionManager == null )
throw new ApplicationException( "SearchControl -- Action Manager is null" );
if( _searchQueryCombo == null )
throw new ApplicationException( "SearchControl -- ComboBoxControl is null" );
#endregion Preconditions
// Repetitious pressing of Ctrl-E enumerates all providers in turn.
if( e.KeyData == ( Keys.Control | Keys.E ))
{
int current = _searchProviders.IndexOf( _currentProvider );
if( current != -1 )
{
current = (current != _searchProviders.Count - 1) ? (current + 1) : 0;
ChangeProviderTo( current );
}
}
else
if( e.KeyData == ( Keys.Control | Keys.Shift | Keys.E ))
{
int current = _searchProviders.IndexOf( _currentProvider );
if( current != -1 )
{
current = (current > 0) ? (current - 1) : (_searchProviders.Count - 1);
ChangeProviderTo( current );
}
}
else
if( !JetTextBox.IsEditorKey( e.KeyData ) && Core.ActionManager.ExecuteKeyboardAction( null, e.KeyData ) )
{
e.Handled = true;
}
else if( e.KeyCode == Keys.Enter )
{
// async processing ensures we don't get a beep (#5442)
Core.UIManager.QueueUIJob( new EventHandler( OnClick ), new object[] {this, EventArgs.Empty} );
e.Handled = true;
}
else if( e.KeyData == ( Keys.Control | Keys.A ))
{
_searchQueryCombo.SelectAll();
}
CurrentSearchText = _searchQueryCombo.Text ?? string.Empty;
}
private void ChangeProviderTo( int index )
{
_currentProvider = (ISearchProvider) _searchProviders[ index ];
_currentProviderItem.Checked = false;
foreach( MenuItem item in _menuProviders.MenuItems )
{
if( item is ProviderMenuItem && ((ProviderMenuItem)item).host == _currentProvider )
{
_currentProviderItem = item;
_currentProviderItem.Checked = true;
Icon icon = ((ProviderMenuItem) item).host.Icon;
_btnProvider.AddIcon( icon, ImageListButton.ButtonState.Normal );
ShowProviderNameTip();
SetTooltip();
break;
}
}
}
private static void _searchQueryCombo_KeyPress( object sender, KeyPressEventArgs e )
{
if( e.KeyChar == '\r' )
{
e.Handled = true;
}
}
private void _searchQueryCombo_SelectedIndexChanged( object sender, EventArgs e )
{
CurrentSearchText = _searchQueryCombo.Text;
}
private void _searchQueryCombo_Leave( object sender, EventArgs e )
{
CurrentSearchText = _searchQueryCombo.Text;
}
private void _searchQueryCombo_Enter( object sender, EventArgs e )
{
_searchQueryCombo.Items.Clear();
LoadSavedQueries();
}
#endregion SearchQuery Combobox Events
#region Provider Button Events
private void _btnProviderChooser_Click(object sender, EventArgs e)
{
_menuProviders.Show(_btnProvider, new Point( 0, _btnProvider.Height ));
}
private void onProviderSelected( object sender, EventArgs e )
{
ProviderMenuItem mi = (ProviderMenuItem) sender;
_currentProviderItem.Checked = false;
mi.Checked = true;
_currentProviderItem = mi;
_currentProvider = mi.host;
_btnProvider.AddIcon( mi.host.Icon, ImageListButton.ButtonState.Normal );
_searchQueryCombo.Invalidate();
ShowProviderNameTip();
SetTooltip();
}
#endregion Provider Button Events
#region ICommandBar Interface Members
public void SetSite( ICommandBarSite site )
{
_site = site;
_grip.SetSite( site );
}
public Size MinSize
{
get { return new Size( 3 + 3 + 3 + 2 + c_nMinComboWidth, (int) (22 * _sizeScale.Height) ); }
}
public Size MaxSize
{
get { return new Size( int.MaxValue, int.MaxValue ); }
}
public Size OptimalSize
{
get { return new Size( 350, (int) (27 * _sizeScale.Height) ); }
}
public Size Integral
{
get { return new Size( 1, 1 ); }
}
#endregion
#region Operations
private void EnableCtrl()
{
EnableControls( true );
SetTooltip();
}
///
/// Enables or disables the bar's controls
/// (without disabling the toolbar itself which allows to drag it while the controls are disabled).
///
/// The desired enabled/disabled state.
public void EnableControls( bool enable )
{
if( Core.State != CoreState.ShuttingDown )
{
foreach( Control control in Controls )
control.Enabled = enable;
_btnProvider.BackColor = _searchQueryCombo.EditBkColor;
}
}
public void Populate()
{
if( !Core.TextIndexManager.IsIndexPresent() )
{
EnableControls( false );
SetTooltip( "Text index is not yet available" );
Core.TextIndexManager.IndexLoaded += OnIndexConstructionComplete;
}
_searchQueryCombo.Text = string.Empty;
InitializeSearchProviders();
}
public void FocusSearchBox()
{
_searchQueryCombo.Focus();
}
public void SetText( string text )
{
_searchQueryCombo.Text = text;
}
public void ShowAdvancedSearchDialog()
{
if( AdvSForm == null || AdvSForm.IsDisposed )
{
string searchText = CurrentSearchText.Trim();
Trace.WriteLine( "SearchCtrl -- text for advanced search is [" + searchText + "]" );
AdvSForm = new AdvancedSearchForm( searchText );
AdvSForm.Show();
}
else
AdvSForm.Activate();
}
private string ProviderTitle
{
get { return (_currentProvider == null) ? string.Empty : _currentProvider.Title; }
}
private void SetTooltip()
{
SetTooltip( ProviderTitle );
}
private void SetTooltip( string text )
{
_tipReason.SetToolTip( this, text );
_tipReason.SetToolTip( _btnProvider, text );
_tipReason.SetToolTip( _btnProviderChooser, _ChooserTooltip );
_tipReason.SetToolTip( _btnSearch, text );
_tipReason.SetToolTip( _searchQueryCombo, text );
}
private void ShowProviderNameTip()
{
if( ( !_searchQueryCombo.Focused && String.IsNullOrEmpty( _searchQueryCombo.Text )) ||
_searchQueryCombo.ForeColor == SystemColors.GrayText )
{
_searchQueryCombo.ForeColor = SystemColors.GrayText;
_searchQueryCombo.Text = ProviderTitle;
}
}
private void HideProviderNameTip()
{
if( _searchQueryCombo.ForeColor == SystemColors.GrayText )
{
_searchQueryCombo.ForeColor = SystemColors.InfoText;
_searchQueryCombo.Text = string.Empty;
}
}
#endregion
private void _panelChoosingButtons_EnabledChanged(object sender, EventArgs e)
{
_panelChoosingButtons.BackColor = _panelChoosingButtons.Enabled ? Color.White : SystemColors.ControlDark;
}
}
#region Menu Items
internal class ProviderMenuItem : MenuItem
{
private const int _LeftIndent = 0;
private const int _InterIconsIndent = 5;
public ISearchProvider host;
public ProviderMenuItem( ISearchProvider isp, EventHandler eh ) : base( isp.ToString(), eh )
{
host = isp;
}
public static void mi_MeasureItem(object sender, MeasureItemEventArgs e)
{
ProviderMenuItem pmi = (ProviderMenuItem) sender;
ISearchProvider isp = pmi.host;
string text = isp.Title;
Icon icon = isp.Icon;
SizeF textSize = e.Graphics.MeasureString( text, SystemInformation.MenuFont );
e.ItemHeight = Math.Max( icon.Height, (int) Math.Ceiling( textSize.Height) );
e.ItemWidth = _LeftIndent + icon.Width + 5 + (int) Math.Ceiling( textSize.Width );
}
public static void mi_DrawItem(object sender, DrawItemEventArgs e)
{
ProviderMenuItem pmi = (ProviderMenuItem) sender;
ISearchProvider isp = pmi.host;
string text = isp.Title;
Icon icon = isp.Icon;
Font font = SystemInformation.MenuFont;
Rectangle glyphRegion = e.Bounds, iconRegion = e.Bounds, textRegion = e.Bounds;
glyphRegion.X = _LeftIndent;
glyphRegion.Width = SystemInformation.MenuCheckSize.Width;
iconRegion.X += _LeftIndent + SystemInformation.MenuCheckSize.Width;
iconRegion.Width = icon.Width;
textRegion.X += _LeftIndent + SystemInformation.MenuCheckSize.Width + icon.Width + _InterIconsIndent;
e.DrawBackground();
if( (e.State & DrawItemState.Checked) != 0 )
ControlPaint.DrawMenuGlyph( e.Graphics, glyphRegion, MenuGlyph.Bullet );
e.Graphics.DrawIcon( icon, iconRegion );
Brush brush = ((e.State & DrawItemState.Selected) != 0) ?
SystemBrushes.FromSystemColor( SystemColors.Menu ) :
SystemBrushes.FromSystemColor( SystemColors.MenuText );
e.Graphics.DrawString( text, font, brush, textRegion );
}
}
internal class ProvidersHeaderMenuItem : MenuItem
{
private readonly string _strHeader;
private readonly static Font _itemFont = new Font(SystemInformation.MenuFont.FontFamily, 8.25f, FontStyle.Bold);
public string Header { get{ return _strHeader; } }
public ProvidersHeaderMenuItem( string header ) : base( header )
{
_strHeader = header;
}
public static void mi_MeasureItem(object sender, MeasureItemEventArgs e)
{
SizeF textSize = e.Graphics.MeasureString( ((ProvidersHeaderMenuItem) sender).Header, _itemFont );
e.ItemHeight = (int) Math.Ceiling( textSize.Height );
e.ItemWidth = (int) Math.Ceiling( textSize.Width );
}
public static void mi_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
Brush brush = ((e.State & DrawItemState.Selected) != 0) ?
SystemBrushes.FromSystemColor( SystemColors.Menu ) :
SystemBrushes.FromSystemColor( SystemColors.MenuText );
e.Graphics.DrawString( ((ProvidersHeaderMenuItem) sender).Header, _itemFont, brush, e.Bounds );
}
}
#endregion Menu Items
internal class SelfDrawnPanelWithBorder : Panel
{
public SelfDrawnPanelWithBorder()
{
SetStyle( ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true );
}
}
#region ACMarginableComboBox
internal class ACMarginableComboBox : ComboBox
{
private const int cMargin = 26;
private Control _control;
public void Attach( Control control )
{
_control = control;
KeyPress += OnKeyPress;
MoveControl();
}
#region OnKeyPress
private void OnKeyPress( object sender, KeyPressEventArgs e )
{
if ( !e.KeyChar.Equals( (char)8 ) )
SearchItems( e );
else
e.Handled = false;
}
///
/// Searches the combo box item list for a match and selects it.
/// If no match is found, then selected index defaults to -1.
///
private void SearchItems( KeyPressEventArgs e )
{
int selectionStart = SelectionStart;
int selectionLength = SelectionLength;
int selectionEnd = selectionStart + selectionLength;
StringBuilder sb = new StringBuilder();
sb.Append( Text.Substring( 0, selectionStart ) )
.Append( e.KeyChar.ToString() )
.Append( Text.Substring( selectionEnd ) );
int index = FindString( sb.ToString() );
e.Handled = (index != -1);
if( e.Handled )
{
SelectedIndex = index;
Select( selectionStart + 1, Text.Length - (selectionStart + 1) );
}
}
#endregion OnKeyPress
#region Controls Movement
protected override void OnLayout( LayoutEventArgs levent )
{
base.OnLayout( levent );
// Don't allow the editbox text go under the button
SetNearMargin( this, cMargin );
MoveControl();
}
private void MoveControl()
{
if (_control != null)
{
Point currentLocation = _control.Location;
RECT rcWindow = new RECT();
IntPtr editHandle = ComboEdithWnd( Handle );
Win32Declarations.GetWindowRect(editHandle, ref rcWindow);
Point moveTo = new Point( rcWindow.left + 2,
rcWindow.top + ((rcWindow.bottom - rcWindow.top) - _control.Height) / 2);
moveTo = _control.Parent.PointToClient( moveTo );
if( !currentLocation.Equals( moveTo ) )
{
_control.Location = moveTo;
_control.BringToFront();
}
}
}
/// Gets the handle of the TextBox contained within a
/// ComboBox control.
private static IntPtr ComboEdithWnd( IntPtr handle )
{
handle = Win32Declarations.FindWindowEx( handle, IntPtr.Zero, "EDIT", "\0" );
return handle;
}
public Color EditBkColor
{
get
{
int val = Win32Declarations.GetBkColor( ComboEdithWnd( Handle ) );
return Color.FromArgb( val );
}
}
///
/// Sets the far margin of a TextBox control or the
/// TextBox contained within a ComboBox.
///
public static void SetNearMargin( Control ctl, int margin )
{
IntPtr handle = ctl.Handle;
if( typeof( ComboBox ).IsAssignableFrom( ctl.GetType() ))
{
handle = ComboEdithWnd(handle);
}
Win32Declarations.SendMessage( handle, Win32Declarations.EM_SETMARGINS, (IntPtr)Win32Declarations.EC_LEFTMARGIN, (IntPtr)margin );
}
#endregion Controls Movement
protected override void OnEnabledChanged( EventArgs a )
{
base.OnEnabledChanged( a );
_control.Visible = Enabled;
}
}
#endregion ACMarginableComboBox
}