~ubuntu-branches/ubuntu/karmic/moon/karmic

« back to all changes in this revision

Viewing changes to class/Microsoft.SilverlightControls/Controls/Src/ScrollBar/ScrollBar.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2009-02-14 12:01:08 UTC
  • Revision ID: james.westby@ubuntu.com-20090214120108-06539vb25vhbd8bn
Tags: upstream-1.0
ImportĀ upstreamĀ versionĀ 1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright Ā© Microsoft Corporation. 
 
2
// This source is subject to the Microsoft Source License for Silverlight Controls (March 2008 Release).
 
3
// Please see http://go.microsoft.com/fwlink/?LinkID=111693 for details.
 
4
// All other rights reserved. 
 
5
 
 
6
using System.Diagnostics;
 
7
using System.Windows.Input; 
 
8
using System.Windows.Markup; 
 
9
using System.Windows.Media.Animation;
 
10
using System.Windows.Media;
 
11
using System.Windows.Controls;
 
12
//using System.Windows.Controls.Primitives;
 
13
 
 
14
namespace System.Windows.Controls.Primitives
 
15
 
16
    /// <summary>
 
17
    ///    ScrollBars are the UI widgets that both let a user drive scrolling from the UI
 
18
    ///    and indicate status of scrolled content. 
 
19
    ///    These are used inside the ScrollViewer. 
 
20
    ///    Their visibility is determined by the scroller visibility properties on ScrollViewer.
 
21
    /// </summary> 
 
22
    [TemplatePart(Name = ScrollBar.ElementRootName, Type = typeof(FrameworkElement))]
 
23
    [TemplatePart(Name = ScrollBar.ElementHorizontalTemplateName, Type = typeof(FrameworkElement))]
 
24
    [TemplatePart(Name = ScrollBar.ElementHorizontalLargeIncreaseName, Type = typeof(RepeatButton))] 
 
25
    [TemplatePart(Name = ScrollBar.ElementHorizontalLargeDecreaseName, Type = typeof(RepeatButton))]
 
26
    [TemplatePart(Name = ScrollBar.ElementHorizontalThumbName, Type = typeof(Thumb))]
 
27
    [TemplatePart(Name = ScrollBar.ElementVerticalTemplateName, Type = typeof(FrameworkElement))] 
 
28
    [TemplatePart(Name = ScrollBar.ElementVerticalLargeIncreaseName, Type = typeof(RepeatButton))] 
 
29
    [TemplatePart(Name = ScrollBar.ElementVerticalLargeDecreaseName, Type = typeof(RepeatButton))]
 
30
    [TemplatePart(Name = ScrollBar.ElementVerticalThumbName, Type = typeof(Thumb))] 
 
31
    [TemplatePart(Name = ScrollBar.StateNormalName, Type = typeof(Storyboard))]
 
32
    [TemplatePart(Name = ScrollBar.StateMouseOverName, Type = typeof(Storyboard))]
 
33
    [TemplatePart(Name = ScrollBar.StateDisabledName, Type = typeof(Storyboard))] 
 
34
    public sealed class ScrollBar : RangeBase
 
35
    {
 
36
        #region Constructor 
 
37
        /// <summary> 
 
38
        /// Constructor to setup the ScrollBar class
 
39
        /// </summary> 
 
40
        public ScrollBar()
 
41
        {
 
42
            Minimum = 0; 
 
43
            Value = 0;
 
44
            Maximum = 10;
 
45
            ViewportSize = 0; 
 
46
 
 
47
            IsEnabled = true;
 
48
            Orientation = Orientation.Horizontal; 
 
49
            MouseEnter += delegate(object sender, MouseEventArgs e) { OnMouseEnter(e); };
 
50
            MouseLeave += delegate(object sender, MouseEventArgs e) { OnMouseLeave(e); };
 
51
            MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs e) { OnMouseLeftButtonDown(e); }; 
 
52
            MouseLeftButtonUp += delegate(object sender, MouseButtonEventArgs e) { OnMouseLeftButtonUp(e); };
 
53
            SizeChanged += delegate { UpdateTrackLayout(GetTrackLength()); };
 
54
        } 
 
55
 
 
56
        /// <summary>
 
57
        /// Apply a template to the ScrollBar. 
 
58
        /// </summary>
 
59
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
 
60
        public override void OnApplyTemplate() 
 
61
        {
 
62
            base.OnApplyTemplate();
 
63
 
 
64
            // Get the parts 
 
65
            ElementRoot = GetTemplateChild(ElementRootName) as FrameworkElement;
 
66
            ElementHorizontalLargeIncrease = GetTemplateChild(ElementHorizontalLargeIncreaseName) as RepeatButton; 
 
67
            ElementHorizontalLargeDecrease = GetTemplateChild(ElementHorizontalLargeDecreaseName) as RepeatButton;
 
68
            ElementHorizontalSmallIncrease = GetTemplateChild(ElementHorizontalSmallIncreaseName) as RepeatButton;
 
69
            ElementHorizontalSmallDecrease = GetTemplateChild(ElementHorizontalSmallDecreaseName) as RepeatButton; 
 
70
            ElementHorizontalThumb = GetTemplateChild(ElementHorizontalThumbName) as Thumb;
 
71
            ElementVerticalTemplate = GetTemplateChild(ElementVerticalTemplateName) as FrameworkElement;
 
72
            ElementVerticalLargeIncrease = GetTemplateChild(ElementVerticalLargeIncreaseName) as RepeatButton; 
 
73
            ElementVerticalLargeDecrease = GetTemplateChild(ElementVerticalLargeDecreaseName) as RepeatButton; 
 
74
            ElementVerticalSmallIncrease = GetTemplateChild(ElementVerticalSmallIncreaseName) as RepeatButton;
 
75
            ElementVerticalSmallDecrease = GetTemplateChild(ElementVerticalSmallDecreaseName) as RepeatButton; 
 
76
            ElementVerticalThumb = GetTemplateChild(ElementVerticalThumbName) as Thumb;
 
77
 
 
78
            // Get the states 
 
79
            if (ElementRoot != null)
 
80
            {
 
81
                StateNormal = ElementRoot.Resources[StateNormalName] as Storyboard; 
 
82
                StateMouseOver = ElementRoot.Resources[StateMouseOverName] as Storyboard; 
 
83
                StateDisabled = ElementRoot.Resources[StateDisabledName] as Storyboard;
 
84
            } 
 
85
 
 
86
            if (ElementHorizontalThumb != null)
 
87
            {
 
88
                ElementHorizontalThumb.DragStarted += new DragStartedEventHandler(OnThumbDragStarted);
 
89
                ElementHorizontalThumb.DragDelta += new DragDeltaEventHandler(OnThumbDragDelta);
 
90
                ElementHorizontalThumb.DragCompleted += new DragCompletedEventHandler(OnThumbDragCompleted);
 
91
            } 
 
92
            if (ElementHorizontalLargeDecrease != null)
 
93
            { 
 
94
                ElementHorizontalLargeDecrease.Click += delegate
 
95
                {
 
96
                    Value -= LargeChange; 
 
97
                    RaiseScrollEvent(ScrollEventType.LargeDecrement);
 
98
                };
 
99
            } 
 
100
            if (ElementHorizontalLargeIncrease != null) 
 
101
            {
 
102
                ElementHorizontalLargeIncrease.Click += delegate 
 
103
                {
 
104
                    Value += LargeChange;
 
105
                    RaiseScrollEvent(ScrollEventType.LargeIncrement); 
 
106
                };
 
107
            }
 
108
            if (ElementHorizontalSmallDecrease != null) 
 
109
            { 
 
110
                ElementHorizontalSmallDecrease.Click += delegate
 
111
                { 
 
112
                    Value -= SmallChange;
 
113
                    RaiseScrollEvent(ScrollEventType.SmallDecrement);
 
114
                }; 
 
115
            }
 
116
            if (ElementHorizontalSmallIncrease != null)
 
117
            { 
 
118
                ElementHorizontalSmallIncrease.Click += delegate 
 
119
                {
 
120
                    Value += SmallChange; 
 
121
                    RaiseScrollEvent(ScrollEventType.SmallIncrement);
 
122
                };
 
123
            } 
 
124
            if (ElementVerticalThumb != null)
 
125
            {
 
126
                ElementVerticalThumb.DragStarted += new DragStartedEventHandler(OnThumbDragStarted);
 
127
                ElementVerticalThumb.DragDelta += new DragDeltaEventHandler(OnThumbDragDelta);
 
128
                ElementVerticalThumb.DragCompleted += new DragCompletedEventHandler(OnThumbDragCompleted);
 
129
            } 
 
130
            if (ElementVerticalLargeDecrease != null)
 
131
            {
 
132
                ElementVerticalLargeDecrease.Click += delegate 
 
133
                {
 
134
                    Value -= LargeChange;
 
135
                    RaiseScrollEvent(ScrollEventType.LargeDecrement); 
 
136
                }; 
 
137
            }
 
138
            if (ElementVerticalLargeIncrease != null) 
 
139
            {
 
140
                ElementVerticalLargeIncrease.Click += delegate
 
141
                { 
 
142
                    Value += LargeChange;
 
143
                    RaiseScrollEvent(ScrollEventType.LargeIncrement);
 
144
                }; 
 
145
            } 
 
146
            if (ElementVerticalSmallDecrease != null)
 
147
            { 
 
148
                ElementVerticalSmallDecrease.Click += delegate
 
149
                {
 
150
                    Value -= SmallChange; 
 
151
                    RaiseScrollEvent(ScrollEventType.SmallDecrement);
 
152
                };
 
153
            } 
 
154
            if (ElementVerticalSmallIncrease != null) 
 
155
            {
 
156
                ElementVerticalSmallIncrease.Click += delegate 
 
157
                {
 
158
                    Value += SmallChange;
 
159
                    RaiseScrollEvent(ScrollEventType.SmallIncrement); 
 
160
                };
 
161
            }
 
162
            // Updating states for parts where properties might have been updated through 
 
163
            // XAML before the template was loaded. 
 
164
            OnIsEnabledChanged(IsEnabled);
 
165
            OnOrientationChanged(); 
 
166
            UpdateVisualState();
 
167
        }
 
168
        #endregion Constructor 
 
169
 
 
170
        #region Orientation
 
171
        /// <summary> 
 
172
        /// Gets whether the ScrollBar has an orientation of vertical or horizontal. 
 
173
        /// </summary>
 
174
        public Orientation Orientation 
 
175
        {
 
176
            get { return (Orientation)GetValue(OrientationProperty); }
 
177
            set { SetValue(OrientationProperty, value); } 
 
178
        }
 
179
 
 
180
        /// <summary> 
 
181
        /// Identifies the Orientation dependency property. 
 
182
        /// </summary>
 
183
        public static readonly DependencyProperty OrientationProperty = 
 
184
            DependencyProperty.Register(
 
185
                "Orientation",
 
186
                typeof(Orientation), 
 
187
                typeof(ScrollBar),
 
188
                new PropertyMetadata(OnOrientationPropertyChanged));
 
189
 
 
190
        /// <summary> 
 
191
        /// OrientationProperty property changed handler.
 
192
        /// </summary> 
 
193
        /// <param name="d">ScrollBar that changed Orientation.</param>
 
194
        /// <param name="e">DependencyPropertyChangedEventArgs.</param>
 
195
        private static void OnOrientationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
 
196
        {
 
197
            ScrollBar s = d as ScrollBar;
 
198
            Debug.Assert(s != null); 
 
199
 
 
200
            s.OnOrientationChanged();
 
201
        } 
 
202
 
 
203
        #endregion Orientation
 
204
 
 
205
        #region ViewportSize
 
206
        /// <summary>
 
207
        /// ViewportSize is the amount of the scrolled extent currently visible. 
 
208
        /// For most scrolled content, this value will be bound to one of ScrollViewer's 
 
209
        /// ViewportSize properties. This property is in logical scrolling units.
 
210
        /// </summary> 
 
211
        public double ViewportSize
 
212
        {
 
213
            get { return (double)GetValue(ViewportSizeProperty); } 
 
214
            set { SetValue(ViewportSizeProperty, value); }
 
215
        }
 
216
 
 
217
        /// <summary> 
 
218
        /// Identifies the ViewportSize dependency property.
 
219
        /// </summary> 
 
220
        public static readonly DependencyProperty ViewportSizeProperty =
 
221
            DependencyProperty.Register(
 
222
                "ViewportSize", 
 
223
                typeof(double),
 
224
                typeof(ScrollBar),
 
225
                new PropertyMetadata(OnViewportSizeChanged)); 
 
226
 
 
227
        private static void OnViewportSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
 
228
        { 
 
229
            ScrollBar s = d as ScrollBar;
 
230
            Debug.Assert(s != null);
 
231
 
 
232
            s.UpdateTrackLayout(s.GetTrackLength());
 
233
        }
 
234
 
 
235
        #endregion ViewportSize 
 
236
 
 
237
        #region IsEnabled 
 
238
        /// <summary>
 
239
        /// Gets or sets a value that indicates whether this element is enabled
 
240
        /// in the user interface (UI). 
 
241
        /// </summary>
 
242
        public bool IsEnabled
 
243
        { 
 
244
            get { return (bool)GetValue(IsEnabledProperty); } 
 
245
            set { SetValue(IsEnabledProperty, value); }
 
246
        } 
 
247
 
 
248
        /// <summary>
 
249
        /// Identifies the IsEnabled dependency property. 
 
250
        /// </summary>
 
251
        public static readonly DependencyProperty IsEnabledProperty =
 
252
            DependencyProperty.Register( 
 
253
                "IsEnabled", 
 
254
                typeof(bool),
 
255
                typeof(ScrollBar), 
 
256
                new PropertyMetadata(OnIsEnabledPropertyChanged));
 
257
 
 
258
        /// <summary> 
 
259
        /// IsEnabledProperty property changed handler.
 
260
        /// </summary>
 
261
        /// <param name="d">ScrollBar that changed IsEnabled.</param> 
 
262
        /// <param name="e">DependencyPropertyChangedEventArgs.</param> 
 
263
        private static void OnIsEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
 
264
        { 
 
265
            ScrollBar s = d as ScrollBar;
 
266
            Debug.Assert(s != null);
 
267
 
 
268
            bool value = (bool)e.NewValue;
 
269
            s.OnIsEnabledChanged(value);
 
270
        } 
 
271
 
 
272
        /// <summary>
 
273
        /// Called when the IsEnabled property changes. 
 
274
        /// </summary>
 
275
        /// <param name="isEnabled">New value of the IsEnabled property.</param>
 
276
        private void OnIsEnabledChanged(bool isEnabled) 
 
277
        {
 
278
            if (ElementHorizontalSmallDecrease != null)
 
279
            { 
 
280
                ElementHorizontalSmallDecrease.IsEnabled = isEnabled; 
 
281
            }
 
282
            if (ElementHorizontalLargeDecrease != null) 
 
283
            {
 
284
                ElementHorizontalLargeDecrease.IsEnabled = isEnabled;
 
285
            } 
 
286
            if (ElementHorizontalThumb != null)
 
287
            {
 
288
                ElementHorizontalThumb.IsEnabled = isEnabled; 
 
289
            } 
 
290
            if (ElementHorizontalLargeIncrease != null)
 
291
            { 
 
292
                ElementHorizontalLargeIncrease.IsEnabled = isEnabled;
 
293
            }
 
294
            if (ElementHorizontalSmallIncrease != null) 
 
295
            {
 
296
                ElementHorizontalSmallIncrease.IsEnabled = isEnabled;
 
297
            } 
 
298
            if (ElementVerticalSmallDecrease != null) 
 
299
            {
 
300
                ElementVerticalSmallDecrease.IsEnabled = isEnabled; 
 
301
            }
 
302
            if (ElementVerticalLargeDecrease != null)
 
303
            { 
 
304
                ElementVerticalLargeDecrease.IsEnabled = isEnabled;
 
305
            }
 
306
            if (ElementVerticalThumb != null) 
 
307
            { 
 
308
                ElementVerticalThumb.IsEnabled = isEnabled;
 
309
            } 
 
310
            if (ElementVerticalLargeIncrease != null)
 
311
            {
 
312
                ElementVerticalLargeIncrease.IsEnabled = isEnabled; 
 
313
            }
 
314
            if (ElementVerticalSmallIncrease != null)
 
315
            { 
 
316
                ElementVerticalSmallIncrease.IsEnabled = isEnabled; 
 
317
            }
 
318
 
 
319
            UpdateVisualState();
 
320
        }
 
321
 
 
322
        #endregion IsEnabled
 
323
 
 
324
        #region OnValueChanged 
 
325
 
 
326
        /// <summary>
 
327
        /// Called when the Value property changes. 
 
328
        /// </summary>
 
329
        /// <param name="oldValue">Old value of the Value property.</param>
 
330
        /// <param name="newValue">New value of the Value property.</param> 
 
331
        protected override void OnValueChanged(double oldValue, double newValue)
 
332
        {
 
333
            double trackLength = GetTrackLength(); 
 
334
 
 
335
            base.OnValueChanged(oldValue, newValue);
 
336
 
 
337
            UpdateTrackLayout(trackLength);
 
338
        }
 
339
 
 
340
        /// <summary>
 
341
        /// Called when the Maximum property changes
 
342
        /// </summary> 
 
343
        /// <param name="oldMaximum">Old value of the Maximum property.</param> 
 
344
        /// <param name="newMaximum">New value of the Maximum property.</param>
 
345
        protected override void OnMaximumChanged(double oldMaximum, double newMaximum) 
 
346
        {
 
347
            double trackLength = GetTrackLength();
 
348
 
 
349
            base.OnMaximumChanged(oldMaximum, newMaximum);
 
350
            UpdateTrackLayout(trackLength);
 
351
        } 
 
352
 
 
353
        /// <summary>
 
354
        /// Called when the Minimum property changes 
 
355
        /// </summary>
 
356
        /// <param name="oldMinimum">Old value of the Minimum property.</param>
 
357
        /// <param name="newMinimum">New value of the Minimum property.</param> 
 
358
        protected override void OnMinimumChanged(double oldMinimum, double newMinimum)
 
359
        {
 
360
            double trackLength = GetTrackLength(); 
 
361
 
 
362
            base.OnMinimumChanged(oldMinimum, newMinimum);
 
363
            UpdateTrackLayout(trackLength); 
 
364
        }
 
365
 
 
366
        #endregion 
 
367
 
 
368
        #region MouseEvents
 
369
        /// <summary> 
 
370
        /// Responds to the MouseEnter event. 
 
371
        /// </summary>
 
372
        /// <param name="e">The event data for the MouseEnter event.</param> 
 
373
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "e", Justification = "Compat with WPF.")]
 
374
        private void OnMouseEnter(MouseEventArgs e)
 
375
        { 
 
376
            e.Handled = true;
 
377
            IsMouseOver = true;
 
378
            if ((Orientation == Orientation.Horizontal && ElementHorizontalThumb != null && !ElementHorizontalThumb.IsDragging) || 
 
379
                (Orientation == Orientation.Vertical && ElementVerticalThumb != null && !ElementVerticalThumb.IsDragging)) 
 
380
            {
 
381
                UpdateVisualState(); 
 
382
            }
 
383
        }
 
384
 
 
385
        /// <summary>
 
386
        /// Responds to the MouseLeave event.
 
387
        /// </summary> 
 
388
        /// <param name="e">The event data for the MouseLeave event.</param> 
 
389
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "e", Justification = "Compat with WPF.")]
 
390
        private void OnMouseLeave(MouseEventArgs e) 
 
391
        {
 
392
            e.Handled = true;
 
393
            IsMouseOver = false; 
 
394
            if ((Orientation == Orientation.Horizontal && ElementHorizontalThumb != null && !ElementHorizontalThumb.IsDragging) ||
 
395
                (Orientation == Orientation.Vertical && ElementVerticalThumb != null && !ElementVerticalThumb.IsDragging))
 
396
            { 
 
397
                UpdateVisualState(); 
 
398
            }
 
399
        } 
 
400
 
 
401
        /// <summary>
 
402
        /// Responds to the MouseLeftButtonDown event. 
 
403
        /// </summary>
 
404
        /// <param name="e">The event data for the MouseLeftButtonDown event.</param>
 
405
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "e", Justification = "Compat with WPF.")] 
 
406
        private void OnMouseLeftButtonDown(MouseButtonEventArgs e) 
 
407
        {
 
408
            e.Handled = true; 
 
409
            CaptureMouse();
 
410
        }
 
411
 
 
412
        /// <summary>
 
413
        /// Responds to the MouseLeftButtonUp event.
 
414
        /// </summary> 
 
415
        /// <param name="e">The event data for the MouseLeftButtonUp event.</param> 
 
416
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "e", Justification = "Compat with WPF.")]
 
417
        private void OnMouseLeftButtonUp(MouseButtonEventArgs e) 
 
418
        {
 
419
            e.Handled = true;
 
420
            ReleaseMouseCapture(); 
 
421
            UpdateVisualState();
 
422
        }
 
423
        #endregion MouseEvents 
 
424
 
 
425
        #region ScrollEvent
 
426
        /// <summary> 
 
427
        /// Event that gets fired when the ScrollBar's value is changed
 
428
        /// through the Thumb, RepeatButtons, or Keyboard interaction
 
429
        /// </summary> 
 
430
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1009:DeclareEventHandlersCorrectly", Justification = "Derives from RoutedEventArgs instead of EventArgs")]
 
431
        internal event EventHandler<ScrollEventArgs> Scroll;
 
432
 
 
433
        /// <summary> 
 
434
        /// This raises the Scroll event, passing in the scrollEventType
 
435
        /// as a parameter to let the handler know what triggered this event. 
 
436
        /// </summary>
 
437
        /// <param name="scrollEventType">ScrollEventType</param>
 
438
        internal void RaiseScrollEvent(ScrollEventType scrollEventType) 
 
439
        {
 
440
            ScrollEventArgs newEvent = new ScrollEventArgs(scrollEventType, Value);
 
441
            newEvent.OriginalSource = this; 
 
442
 
 
443
            if (Scroll != null)
 
444
            { 
 
445
                Scroll(this, newEvent);
 
446
            }
 
447
        } 
 
448
 
 
449
        #endregion ScrollEvent
 
450
 
 
451
        #region Change State 
 
452
        /// <summary>
 
453
        /// Update the current visual state of the ScrollBar. 
 
454
        /// </summary>
 
455
        internal void UpdateVisualState()
 
456
        { 
 
457
            if (!IsEnabled)
 
458
            {
 
459
                ChangeVisualState(StateDisabled ?? StateNormal); 
 
460
            } 
 
461
            else
 
462
            { 
 
463
                if (IsMouseOver)
 
464
                {
 
465
                    ChangeVisualState(StateMouseOver ?? StateNormal); 
 
466
                }
 
467
                else
 
468
                { 
 
469
                    ChangeVisualState(StateNormal); 
 
470
                }
 
471
            } 
 
472
        }
 
473
 
 
474
        /// <summary> 
 
475
        /// Change the visual state of the ScrollBar.
 
476
        /// </summary>
 
477
        /// <param name="state">Next visual state of the ScrollBar.</param> 
 
478
        /// <remarks> 
 
479
        /// This method should not be called by controls to force a change to
 
480
        /// the current visual state.  UpdateVisualState is preferred because 
 
481
        /// it properly handles suspension of state changes.
 
482
        /// </remarks>
 
483
        internal void ChangeVisualState(Storyboard state) 
 
484
        {
 
485
            Storyboard previousState = _currentState;
 
486
            if (state == previousState) 
 
487
            { 
 
488
                return;
 
489
            } 
 
490
 
 
491
            if (state != null)
 
492
            { 
 
493
                if (previousState != null)
 
494
                {
 
495
                    previousState.Stop(); 
 
496
                } 
 
497
                _currentState = state;
 
498
                state.Begin(); 
 
499
            }
 
500
        }
 
501
        #endregion Change State 
 
502
 
 
503
        #region ThumbDrag
 
504
 
 
505
        private void OnThumbDragCompleted(Object sender, DragCompletedEventArgs e) 
 
506
        {
 
507
            RaiseScrollEvent(ScrollEventType.EndScroll); 
 
508
        }
 
509
 
 
510
        private void OnThumbDragStarted(Object sender, DragStartedEventArgs e) 
 
511
        {
 
512
            this._dragValue = this.Value;
 
513
        } 
 
514
 
 
515
        /// <summary>
 
516
        /// Whenever the thumb gets dragged, we handle the event through 
 
517
        /// this function to update the current value depending upon the
 
518
        /// thumb drag delta.
 
519
        /// </summary> 
 
520
        /// <param name="e">DragEventArgs</param>
 
521
        private void OnThumbDragDelta(Object sender, DragDeltaEventArgs e)
 
522
        { 
 
523
            double offset = 0; 
 
524
 
 
525
            if (Orientation == Orientation.Horizontal && ElementHorizontalThumb != null) 
 
526
            {
 
527
                offset = e.HorizontalChange / (GetTrackLength() - ElementHorizontalThumb.ActualWidth) * (Maximum - Minimum);
 
528
            } 
 
529
            else if (Orientation == Orientation.Vertical && ElementVerticalThumb != null)
 
530
            {
 
531
                offset = e.VerticalChange / (GetTrackLength() - ElementVerticalThumb.ActualHeight) * (Maximum - Minimum); 
 
532
            } 
 
533
 
 
534
            if (!double.IsNaN(offset) && !double.IsInfinity(offset)) 
 
535
            {
 
536
                _dragValue += offset;
 
537
 
 
538
                double newValue = Math.Min(Maximum, Math.Max(Minimum, _dragValue));
 
539
 
 
540
                if (newValue != Value) 
 
541
                { 
 
542
                    Value = newValue;
 
543
                    RaiseScrollEvent(ScrollEventType.ThumbTrack); 
 
544
                }
 
545
            }
 
546
        } 
 
547
 
 
548
        #endregion ThumbDrag
 
549
 
 
550
        #region UpdateTrackLayout 
 
551
 
 
552
        /// <summary> 
 
553
        /// This code will run whenever Orientation changes, to change the template
 
554
        /// being used to display this control.
 
555
        /// </summary> 
 
556
        private void OnOrientationChanged()
 
557
        {
 
558
            double trackLength = GetTrackLength(); 
 
559
 
 
560
            if (ElementHorizontalTemplate != null)
 
561
            { 
 
562
                ElementHorizontalTemplate.Visibility = (Orientation == Orientation.Horizontal ? Visibility.Visible : Visibility.Collapsed);
 
563
            }
 
564
            if (ElementVerticalTemplate != null) 
 
565
            {
 
566
                ElementVerticalTemplate.Visibility = (Orientation == Orientation.Horizontal ? Visibility.Collapsed : Visibility.Visible);
 
567
            } 
 
568
            UpdateTrackLayout(trackLength); 
 
569
        }
 
570
 
 
571
        /// <summary>
 
572
        /// This method will take the current min, max, and value to
 
573
        /// calculate and layout the current control measurements. 
 
574
        /// </summary>
 
575
        private void UpdateTrackLayout(double trackLength)
 
576
        { 
 
577
            double maximum = Maximum; 
 
578
            double minimum = Minimum;
 
579
            double value = Value; 
 
580
            double multiplier = (value - minimum) / (maximum - minimum);
 
581
 
 
582
            double thumbSize = UpdateThumbSize(trackLength); 
 
583
 
 
584
            if (Orientation == Orientation.Horizontal && ElementHorizontalLargeDecrease != null && ElementHorizontalThumb != null)
 
585
            { 
 
586
                ElementHorizontalLargeDecrease.Width = multiplier * (trackLength - thumbSize); 
 
587
            }
 
588
            else if (Orientation == Orientation.Vertical && ElementVerticalLargeDecrease != null && ElementVerticalThumb != null) 
 
589
            {
 
590
                ElementVerticalLargeDecrease.Height = multiplier * (trackLength - thumbSize);
 
591
            } 
 
592
        }
 
593
 
 
594
        /// <summary> 
 
595
        /// Based on the size of the Large Increase/Decrease RepeatButtons 
 
596
        /// and on the Thumb, we will calculate the size of the track area
 
597
        /// of the ScrollBar 
 
598
        /// </summary>
 
599
        /// <returns>The length of the track</returns>
 
600
        internal double GetTrackLength() 
 
601
        {
 
602
            double length = Double.NaN;
 
603
 
 
604
            if (Orientation == Orientation.Horizontal) 
 
605
            {
 
606
                length = this.ActualWidth; 
 
607
 
 
608
                if (ElementHorizontalSmallDecrease != null)
 
609
                { 
 
610
                    length -= ElementHorizontalSmallDecrease.ActualWidth;
 
611
                }
 
612
                if (ElementHorizontalSmallIncrease != null) 
 
613
                { 
 
614
                    length -= ElementHorizontalSmallIncrease.ActualWidth;
 
615
                } 
 
616
            }
 
617
            else
 
618
            { 
 
619
                length = this.ActualHeight;
 
620
 
 
621
                if (ElementVerticalSmallDecrease != null) 
 
622
                { 
 
623
                    length -= ElementVerticalSmallDecrease.ActualHeight;
 
624
                } 
 
625
                if (ElementVerticalSmallIncrease != null)
 
626
                {
 
627
                    length -= ElementVerticalSmallIncrease.ActualHeight; 
 
628
                }
 
629
            }
 
630
 
 
631
            return length; 
 
632
        }
 
633
 
 
634
        /// <summary>
 
635
        /// Based on the ViewportSize, the Track's length, and the
 
636
        /// Minimum and Maximum values, we will calculate the length 
 
637
        /// of the thumb.
 
638
        /// </summary>
 
639
        /// <returns>Double value representing display unit length</returns> 
 
640
        private double ConvertViewportSizeToDisplayUnits(double trackLength) 
 
641
        {
 
642
            double viewRangeValue = Maximum - Minimum; 
 
643
 
 
644
            return trackLength * ViewportSize / (ViewportSize + viewRangeValue);
 
645
        } 
 
646
 
 
647
        /// <summary>
 
648
        /// This will resize the Thumb, based on calculations with the ViewportSize, 
 
649
        /// the Track's length, and the Minimum and Maximum values. 
 
650
        /// </summary>
 
651
        internal double UpdateThumbSize(double trackLength) 
 
652
        {
 
653
            double result = Double.NaN;
 
654
 
 
655
            if((Orientation == Orientation.Horizontal && ElementHorizontalThumb != null) ||
 
656
                (Orientation == Orientation.Vertical && ElementVerticalThumb != null))
 
657
            { 
 
658
                if (trackLength > 0) 
 
659
                {
 
660
                    // hide the thumb if too big 
 
661
                    if (Maximum - Minimum == 0)
 
662
                    {
 
663
                        ElementHorizontalThumb.Visibility = Visibility.Collapsed; 
 
664
                        ElementVerticalThumb.Visibility = Visibility.Collapsed;
 
665
                    }
 
666
                    else 
 
667
                    { 
 
668
                        result = ConvertViewportSizeToDisplayUnits(trackLength);
 
669
 
 
670
                        ElementHorizontalThumb.Visibility = Visibility.Visible;
 
671
                        ElementVerticalThumb.Visibility = Visibility.Visible;
 
672
 
 
673
                        // calculate size
 
674
                        if (Orientation == Orientation.Horizontal)
 
675
                        { 
 
676
                            ElementHorizontalThumb.Width = result; 
 
677
                            result = ElementHorizontalThumb.ActualWidth;
 
678
                        } 
 
679
                        else
 
680
                        {
 
681
                            ElementVerticalThumb.Height = result; 
 
682
                            result = ElementVerticalThumb.ActualHeight;
 
683
                        }
 
684
                    } 
 
685
                } 
 
686
            }
 
687
 
 
688
            return result;
 
689
        }
 
690
 
 
691
        #endregion UpdateTrackLayout
 
692
 
 
693
        #region Template Parts 
 
694
 
 
695
        /// <summary>
 
696
        /// Root of the ScrollBar template. 
 
697
        /// </summary>
 
698
        internal FrameworkElement ElementRoot { get; set; }
 
699
        internal const string ElementRootName = "RootElement"; 
 
700
 
 
701
        /// <summary>
 
702
        /// Horizontal template root 
 
703
        /// </summary> 
 
704
        internal FrameworkElement ElementHorizontalTemplate { get; set; }
 
705
        internal const string ElementHorizontalTemplateName = "HorizontalRootElement"; 
 
706
 
 
707
        /// <summary>
 
708
        /// Large increase repeat button 
 
709
        /// </summary>
 
710
        internal RepeatButton ElementHorizontalLargeIncrease { get; set; }
 
711
        internal const string ElementHorizontalLargeIncreaseName = "HorizontalLargeIncreaseElement"; 
 
712
 
 
713
        /// <summary>
 
714
        /// Large decrease repeat button 
 
715
        /// </summary>
 
716
        internal RepeatButton ElementHorizontalLargeDecrease { get; set; }
 
717
        internal const string ElementHorizontalLargeDecreaseName = "HorizontalLargeDecreaseElement"; 
 
718
 
 
719
        /// <summary>
 
720
        /// Small increase repeat button 
 
721
        /// </summary> 
 
722
        internal RepeatButton ElementHorizontalSmallIncrease { get; set; }
 
723
        internal const string ElementHorizontalSmallIncreaseName = "HorizontalSmallIncreaseElement"; 
 
724
 
 
725
        /// <summary>
 
726
        /// Small decrease repeat button 
 
727
        /// </summary>
 
728
        internal RepeatButton ElementHorizontalSmallDecrease { get; set; }
 
729
        internal const string ElementHorizontalSmallDecreaseName = "HorizontalSmallDecreaseElement"; 
 
730
 
 
731
        /// <summary>
 
732
        /// Thumb for dragging track 
 
733
        /// </summary>
 
734
        internal Thumb ElementHorizontalThumb { get; set; }
 
735
        internal const string ElementHorizontalThumbName = "HorizontalThumbElement"; 
 
736
 
 
737
        /// <summary>
 
738
        /// Vertical template root 
 
739
        /// </summary> 
 
740
        internal FrameworkElement ElementVerticalTemplate { get; set; }
 
741
        internal const string ElementVerticalTemplateName = "VerticalRootElement"; 
 
742
 
 
743
        /// <summary>
 
744
        /// Large increase repeat button 
 
745
        /// </summary>
 
746
        internal RepeatButton ElementVerticalLargeIncrease { get; set; }
 
747
        internal const string ElementVerticalLargeIncreaseName = "VerticalLargeIncreaseElement"; 
 
748
 
 
749
        /// <summary>
 
750
        /// Large decrease repeat button 
 
751
        /// </summary>
 
752
        internal RepeatButton ElementVerticalLargeDecrease { get; set; }
 
753
        internal const string ElementVerticalLargeDecreaseName = "VerticalLargeDecreaseElement"; 
 
754
 
 
755
        /// <summary>
 
756
        /// Small increase repeat button 
 
757
        /// </summary> 
 
758
        internal RepeatButton ElementVerticalSmallIncrease { get; set; }
 
759
        internal const string ElementVerticalSmallIncreaseName = "VerticalSmallIncreaseElement"; 
 
760
 
 
761
        /// <summary>
 
762
        /// Small decrease repeat button 
 
763
        /// </summary>
 
764
        internal RepeatButton ElementVerticalSmallDecrease { get; set; }
 
765
        internal const string ElementVerticalSmallDecreaseName = "VerticalSmallDecreaseElement"; 
 
766
 
 
767
        /// <summary>
 
768
        /// Thumb for dragging track 
 
769
        /// </summary>
 
770
        internal Thumb ElementVerticalThumb { get; set; }
 
771
        internal const string ElementVerticalThumbName = "VerticalThumbElement"; 
 
772
 
 
773
        /// <summary>
 
774
        /// Transition into the Normal state in the ScrollBar template. 
 
775
        /// </summary> 
 
776
        internal Storyboard StateNormal { get; set; }
 
777
        internal const string StateNormalName = "Normal State"; 
 
778
 
 
779
        /// <summary>
 
780
        /// Transition into the MouseOver state in the ScrollBar template. 
 
781
        /// </summary>
 
782
        internal Storyboard StateMouseOver { get; set; }
 
783
        internal const string StateMouseOverName = "MouseOver State"; 
 
784
 
 
785
        /// <summary>
 
786
        /// Transition into the Disabled state in the ScrollBar template. 
 
787
        /// </summary>
 
788
        internal Storyboard StateDisabled { get; set; }
 
789
        internal const string StateDisabledName = "Disabled State"; 
 
790
 
 
791
        #endregion Template Parts
 
792
 
 
793
        #region Member Variables 
 
794
        /// <summary>
 
795
        /// Whether the mouse is currently over the control 
 
796
        /// </summary>
 
797
        internal bool IsMouseOver { get; set; }
 
798
 
 
799
        /// <summary>
 
800
        /// Current state of the control
 
801
        /// </summary> 
 
802
        internal Storyboard _currentState; 
 
803
 
 
804
        /// <summary> 
 
805
        /// Accumulates drag offsets in case the mouse drags off the end of the track.
 
806
        /// </summary>
 
807
        private double _dragValue; 
 
808
        #endregion Member Variables
 
809
    }
 
810