/// /// 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.ComponentModel; using System.Drawing; using System.Windows.Forms; using JetBrains.Omea.GUIControls; using JetBrains.Omea.GUIControls.CommandBar; using JetBrains.Omea.OpenAPI; namespace JetBrains.Omea { /// /// Implements a docked line with the resource tabs conrtol and search control. /// public class ResourceTabsRow : UserControl, ICommandBarSite { #region Data /// /// Required designer variable. /// private Container components = null; /// /// The resource tabs control. /// internal TabSwitcher _barResourceTypeTabs; /// /// The Search control. /// protected SearchCtrl _barSearch; /// /// Gap between the search control and the resourec tabs control. /// private static readonly int c_nGap = 10; /// /// Horizontal margin of this control. /// private static readonly int c_nHorMargin = 2; /// /// Vertical margin of this control. /// private static readonly int c_nVerMargin = 0; /// /// Regulates the desired width of the toolbar, as it was adjusted by the user. /// Initially populated with the of the toolbar in . /// Persisted in settings. /// protected int _nDesiredToolbarWidth; #endregion #region Construction public ResourceTabsRow() { // This call is required by the Windows.Forms Form Designer. InitializeComponentSelf(); } /// /// Clean up any resources being used. /// protected override void Dispose( bool disposing ) { if( disposing ) { if( components != null ) { components.Dispose(); } } base.Dispose( disposing ); } #endregion #region Visual Init /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponentSelf() { components = new Container(); using( new LayoutSuspender( this ) ) { // _barResourceTypeTabs _barResourceTypeTabs = new TabSwitcher(); _barResourceTypeTabs.Font = new Font( "Tahoma", 9.75F, FontStyle.Regular, GraphicsUnit.Point, ((Byte) (204)) ); _barResourceTypeTabs.Name = "_barResourceTypeTabs"; _barResourceTypeTabs.TabIndex = 1; _barResourceTypeTabs.Location = new Point( 0, 6 ); _barResourceTypeTabs.Size = new Size( 648, 27 ); _barResourceTypeTabs.SetSite( this ); // _barSearch _barSearch = new SearchCtrl(); _barSearch.Name = "_barSearch"; _barSearch.TabIndex = 2; _barSearch.Size = _barSearch.OptimalSize; _barSearch.SetSite( this ); _nDesiredToolbarWidth = _barSearch.OptimalSize.Width; // This Control Height = 32; Controls.Add( _barResourceTypeTabs ); Controls.Add( _barSearch ); SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.CacheText | ControlStyles.ContainerControl | ControlStyles.ResizeRedraw | ControlStyles.Selectable | ControlStyles.UserPaint | ControlStyles.Opaque , true ); } } #endregion #region ICommandBarSite Interface Members public bool RequestMove( ICommandBar sender, Size offset ) { if( !Object.ReferenceEquals( sender, _barSearch ) ) throw new InvalidOperationException(); _nDesiredToolbarWidth = _barSearch.Width - offset.Width; // Calc the new desired size _nDesiredToolbarWidth = _nDesiredToolbarWidth >= 1 ? _nDesiredToolbarWidth : 1; // Constrain PerformLayout(); // Apply the new desired width to the layout Refresh(); return true; // Move allowed } public bool RequestSize( ICommandBar sender, Size difference ) { throw new InvalidOperationException(); } public bool PerformLayout( ICommandBar sender ) { Core.UserInterfaceAP.QueueJob( "Layout the Row", new MethodInvoker( PerformLayout ) ); return true; } #endregion #region Implementation — Overrides protected override void OnLayout( LayoutEventArgs levent ) { using( new LayoutSuspender( _barSearch ) ) using( new LayoutSuspender( _barResourceTypeTabs ) ) { // Client rectangle that encounters for the margins Rectangle client = ClientRectangle; client.Inflate( -c_nHorMargin, -c_nVerMargin ); // Collect the minimax sizes of the controls Size sizeSearchMax = _barSearch.MaxSize; Size sizeSearchMin = _barSearch.MinSize; Size sizeSearchOpt = _barSearch.OptimalSize; Size sizeTabsMin = _barResourceTypeTabs.MinSize; Size sizeTabsMax = _barResourceTypeTabs.MaxSize; Size sizeTabsOpt = _barResourceTypeTabs.OptimalSize; // Restrict the search bar width int nSearchWidth = _nDesiredToolbarWidth; bool bSearch = true; // Presence of the control in the layout nSearchWidth = nSearchWidth >= sizeSearchMin.Width ? (nSearchWidth <= sizeSearchMax.Width ? nSearchWidth : sizeSearchMax.Width) : sizeSearchMin.Width; if( (sizeSearchMin.Width > client.Width) || (sizeSearchMin.Height > client.Height) ) { nSearchWidth = 0; // Hide the search control if it does not fit bSearch = false; } // Restrict the resource tabs bar width int nResourceTabsWidth; bool bResourceTabs = true; // Presence of the control in the layout if( (sizeTabsMin.Width > client.Width) || (sizeTabsMin.Height > client.Height) ) // Resource tabs do not fit at all { nResourceTabsWidth = 0; bResourceTabs = false; } else // Resource tabs do fit { nResourceTabsWidth = client.Width - (bSearch ? nSearchWidth + c_nGap : 0); // Occupy the available space nResourceTabsWidth = nResourceTabsWidth >= 0 ? nResourceTabsWidth : 0; // Don't allow to drop below zero nResourceTabsWidth = nResourceTabsWidth <= sizeTabsMax.Width ? nResourceTabsWidth : sizeTabsMax.Width; // Limit by respecting the maximum size } // Negotiate the sizes, in case the resource tabs are present if( bResourceTabs ) { // Resource tabs do not fit? Remove the gap. if( (nResourceTabsWidth < sizeTabsMin.Width) && (bSearch) ) nResourceTabsWidth += c_nGap; // Remove the gap if short on space // Resource tabs still do not fit? Try shrinking the search control if( (nResourceTabsWidth < sizeTabsMin.Width) && (bSearch) ) { nSearchWidth = client.Width - sizeTabsMin.Width; // Try to shrink the search control nSearchWidth = nSearchWidth >= sizeSearchMin.Width ? (nSearchWidth <= sizeSearchMax.Width ? nSearchWidth : sizeSearchMax.Width) : sizeSearchMin.Width; // Constrain its new width nResourceTabsWidth = client.Width - nSearchWidth; // Update the possible tabs width (no gap at this point) } // Resource tabs still do not fit? Drop the search control at all if( (nResourceTabsWidth < sizeTabsMin.Width) && (bSearch) ) { nSearchWidth = 0; bSearch = false; nResourceTabsWidth = client.Width - nSearchWidth; // Update the possible tabs width } // Resource tabs still do not fit? Drop em! if( nResourceTabsWidth < sizeTabsMin.Width ) { bResourceTabs = false; nResourceTabsWidth = 0; } } ////////////////////////// // Apply layouting to the controls. // Resource tabs if( (bResourceTabs) && (nResourceTabsWidth > 0) ) { _barResourceTypeTabs.Left = client.Left; _barResourceTypeTabs.Height = sizeTabsOpt.Height <= client.Height ? sizeTabsOpt.Height : client.Height; // No more than optimal height _barResourceTypeTabs.Top = client.Bottom - _barResourceTypeTabs.Height; // Align at bottom _barResourceTypeTabs.Visible = true; _barResourceTypeTabs.Width = nResourceTabsWidth; } else _barResourceTypeTabs.Visible = false; // Search Control if( (bSearch) && (nSearchWidth > 0) ) { // Fits, place it _barSearch.Width = nSearchWidth; _barSearch.Left = client.Right - _barSearch.Width; _barSearch.Height = sizeSearchOpt.Height < client.Height ? sizeSearchOpt.Height : client.Height; _barSearch.Top = client.Top + (client.Height - _barSearch.Height) / 2; // Center vertically in the space _barSearch.Visible = true; } else // Does not fit, turn off _barSearch.Visible = false; } // Apply the visual changes Invalidate( false ); } protected override void OnPaint( PaintEventArgs e ) { using( Brush brush = new SolidBrush( SystemColors.Control ) ) e.Graphics.FillRectangle( brush, ClientRectangle ); } #endregion #region Attributes /// /// Gets the Resource Type Tabs control. /// internal TabSwitcher ResourceTypeTabs { get { return _barResourceTypeTabs; } } /// /// Gets the Search control. /// public SearchCtrl SearchBar { get { return _barSearch; } } /// /// The desired search bar width (that is acquired as soon as it does not conflict with min-size, max-size, and presence of the resource tabs). /// This is the value that should be persisted. /// public int DesiredSearchBarWidth { get { return _nDesiredToolbarWidth; } set { if(value <= 0) throw new ArgumentOutOfRangeException("value", value, "The desired width must be a positive value."); _nDesiredToolbarWidth = value; } } #endregion #region Operations /// /// Saves or loads the resource tabs row settings. /// /// True to save, False to load. public void SerializeSettings(bool isStoring) { string section = "MainForm"; string sDesiredToolbarWidth = "ResourceTabsRow.DesiredToolbarWidth"; if(isStoring) Core.SettingStore.WriteInt( section, sDesiredToolbarWidth, _nDesiredToolbarWidth ); else _nDesiredToolbarWidth = Core.SettingStore.ReadInt( section, sDesiredToolbarWidth, _nDesiredToolbarWidth ); } #endregion } }