// ***************************************************************************** // // © Component Factory Pty Ltd 2017. All rights reserved. // The software and associated documentation supplied hereunder are the // proprietary information of Component Factory Pty Ltd, 13 Swallows Close, // Mornington, Vic 3931, Australia and are supplied subject to licence terms. // // Version 4.5.0.0 www.ComponentFactory.com // ***************************************************************************** using System; using System.Text; using System.Drawing; using System.Drawing.Drawing2D; using System.Collections.Generic; using System.Windows.Forms; using System.Diagnostics; namespace ComponentFactory.Krypton.Toolkit { /// <summary> /// View element that draws a scrollbar. /// </summary> public class ViewDrawScrollBar : ViewLeaf { #region Instance Fields private ScrollBar _scrollBar; private bool _vertical; private bool _removing; private bool _shortSize; private int _min; private int _max; private int _largeChange; private int _smallChange; private int _offset; #endregion #region Events /// <summary> /// Occurs when the scroll position has changed. /// </summary> public event EventHandler ScrollChanged; #endregion #region Identity /// <summary> /// Initialize a new instance of the ViewDrawScrollBar class. /// </summary> /// <param name="vertical">Is this a vertical scrollbar.</param> public ViewDrawScrollBar(bool vertical) { // Remember the vertical/horizontal setting _vertical = vertical; //Default other properties _removing = false; _shortSize = false; _min = 0; _max = 100; _largeChange = 20; _smallChange = 1; _offset = 0; } /// <summary> /// Obtains the String representation of this instance. /// </summary> /// <returns>User readable name of the instance.</returns> public override string ToString() { // Return the class name and instance identifier return "ViewDrawScrollBar:" + Id; } /// <summary> /// Release unmanaged and optionally managed resources. /// </summary> /// <param name="disposing">Called from Dispose method.</param> protected override void Dispose(bool disposing) { // If called from explicit call to Dispose if (disposing) { // Must remove the scroll bar resource if (_scrollBar != null) { // Should never be called from garbage collector Debug.Assert(!_scrollBar.InvokeRequired); // Cannot destroy control in a different thread if (!_scrollBar.InvokeRequired) RemoveScrollBar(); } } base.Dispose(disposing); } #endregion #region Vertical /// <summary> /// Gets and sets a value indicating if the scrollbar is vertical. /// </summary> public bool Vertical { get { return _vertical; } set { // Only interested in changes if (_vertical != value) { // Remember new orientation _vertical = value; // Remove the scrollbar as a child control RemoveScrollBar(); } } } #endregion #region ShortSize /// <summary> /// Gets and sets a value indicating if the scroll should short size. /// </summary> public bool ShortSize { get { return _shortSize; } set { _shortSize = value; } } #endregion #region SetScrollValues /// <summary> /// Update the scrollbar with the latest scrolling values. /// </summary> /// <param name="min">Scroll minimum value.</param> /// <param name="max">Scroll maximum value.</param> /// <param name="smallChange">Size of a small change.</param> /// <param name="largeChange">Size of a large change.</param> /// <param name="offset">Current scrolling offset.</param> public void SetScrollValues(int min, int max, int smallChange, int largeChange, int offset) { // Update cached values (applying limit checking) _min = Math.Max(min, 0); _max = Math.Max(max, 0); _smallChange = Math.Max(smallChange, 0); _largeChange = Math.Max(largeChange, 0); _offset = Math.Max(offset, 0); if (_scrollBar != null) { // Set the scrolling values _scrollBar.Minimum = _min; _scrollBar.Maximum = _max; _scrollBar.SmallChange = _smallChange; _scrollBar.LargeChange = _largeChange; _scrollBar.Value = Math.Max(_min, Math.Min(_max, _offset)); } } #endregion #region ScrollPosition /// <summary> /// Gets the current scroll position. /// </summary> public int ScrollPosition { get { if (_scrollBar != null) return _scrollBar.Value; else return 0; } } #endregion #region Layout /// <summary> /// Discover the preferred size of the element. /// </summary> /// <param name="context">Layout context.</param> public override Size GetPreferredSize(ViewLayoutContext context) { Debug.Assert(context != null); // The minimum size is the minimum system size of a scrollbar return new Size(SystemInformation.VerticalScrollBarWidth, SystemInformation.HorizontalScrollBarHeight); } /// <summary> /// Perform a layout of the elements. /// </summary> /// <param name="context">Layout context.</param> public override void Layout(ViewLayoutContext context) { Debug.Assert(context != null); // Prevent recreate of the control if (!IsDisposed && !_removing) { // We take on all the available display area ClientRectangle = context.DisplayRectangle; // Are we allowed to layout child controls? if (!context.ViewManager.DoNotLayoutControls) { // Make sure the scrollbar has actually been created CreateScrollBar(context.Control); // If we need to hide/disable the control then do it before position changes if (!Visible) _scrollBar.Hide(); if (!Enabled) _scrollBar.Enabled = false; // Should the scrollbar is shorter than then the entire client area? if (ShortSize) { if (Vertical) _scrollBar.SetBounds(ClientLocation.X, ClientLocation.Y, ClientWidth, ClientHeight - SystemInformation.HorizontalScrollBarHeight); else _scrollBar.SetBounds(ClientLocation.X, ClientLocation.Y, ClientWidth - SystemInformation.VerticalScrollBarWidth, ClientHeight); } else { // Position the ScrollBar in the entire requested area _scrollBar.SetBounds(ClientLocation.X, ClientLocation.Y, ClientWidth, ClientHeight); } // If we need to show/enable control then do it after position changes if (Visible) _scrollBar.Show(); if (Enabled) _scrollBar.Enabled = true; } } } #endregion #region Implementation private void CreateScrollBar(Control parent) { // Do we need to create a scrollbar? if (_scrollBar == null) { // Create the correct type of control if (Vertical) _scrollBar = new VScrollBar(); else _scrollBar = new HScrollBar(); // Hook into scroll position changes _scrollBar.Scroll += new ScrollEventHandler(OnScrollBarChange); // Create it hidden _scrollBar.Hide(); // Set the scrolling values _scrollBar.Minimum = _min; _scrollBar.Maximum = _max; _scrollBar.SmallChange = _smallChange; _scrollBar.LargeChange = _largeChange; _scrollBar.Value = _offset; // Add our new control to the provided parent collection CommonHelper.AddControlToParent(parent, _scrollBar); } } private void RemoveScrollBar() { // Do we need to remove the scrollbar? if ((_scrollBar != null) && !_removing) { // Prevent recreate of the control during removal, as removing it // will cause more layout cycles to occur. We put it back to false // at the end of the remove process. _removing = true; // Unhook from events _scrollBar.Scroll -= new ScrollEventHandler(OnScrollBarChange); // Hide the scrollbar from view _scrollBar.Hide(); // Remove scrollbar from containing collection CommonHelper.RemoveControlFromParent(_scrollBar); // Destroy the current scrollbar _scrollBar.Dispose(); _scrollBar = null; _removing = false; } } private void OnScrollBarChange(object sender, ScrollEventArgs e) { // Update with the new scroll value _scrollBar.Value = e.NewValue; if (ScrollChanged != null) ScrollChanged(this, EventArgs.Empty); } #endregion } }