Sign in Join
Wiki copytemporary

macOS Progress Indicators: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: macOS Progress Indicators

OldNewLine
1+*(macOS only)*
2+
3+## Overview
4+
5+Progress indicators can be *determinate* or *indeterminate*. A determinate indicator displays the completion percentage of a task. An indeterminate indicator shows that the application is busy without providing a visual indication of how long the task will take.
6+
7+The NSProgressIndicator class is an interface that provides visual feedback to the user about the status of an ongoing task and is part of the AppKit framework. The class is available in all versions of macOS since Mac OS X 10.0 (Cheetah). The *style* (spinning or bar), *sizeToFit* (resize based on style) and *isDisplayedWhenStopped* (hide when not active) properties were introduced in Mac OS X 10.2 (Jaguar).
8+
9+## Example code
10+
11+![](/wiki-images/6/69/Macos_native_progress_indicators.png)
12+
13+The code below implements the four progress indicators annotated in the above image: the determinate progress indicators bar and circle and the indeterminate progress indicators spinner and bar2.
14+
15+``` pascal
16+unit Unit1;
17+
18+{$mode objfpc}{$H+}
19+{$modeswitch objectivec1}
20+{$linkframework appkit}
21+
22+interface
23+
24+uses
25+ Forms, Controls, StdCtrls,
26+ ExtCtrls, // for timers
27+ CocoaAll, // for Cocoa vars etc
28+ MacOSAll, // for data types eg CGFloat
29+ CTypes; // for data types eg CUInt
30+
31+type
32+
33+ NSProgressIndicator = objcclass external (NSView)
34+ private
35+ _isBezeled: ObjCBOOL;
36+ _isIndeterminate: ObjCBOOL;
37+ _threadedAnimation: ObjCBOOL;
38+ _minimum: double;
39+ _maximum: double;
40+ _value: double;
41+ _animationIndex: cuint;
42+ _animationDelay: NSTimeInterval;
43+ _timer: id;
44+ _drawingWidth: CGFloat;
45+ _roundColor: id;
46+ _reserved: id;
47+ __progressIndicatorFlags: bitpacked record
48+ case byte of
49+ 0: (_anonBitField___progressIndicatorFlags0: cuint);
50+ 1: (
51+ isSpinning: 0..1;
52+ isVector: 0..1;
53+ isLocked: 0..1;
54+ controlTint: 0..((1 shl 3)-1);
55+ controlSize: 0..((1 shl 2)-1);
56+ style: 0..1;
57+ _delayedStartup: 0..1;
58+ hideWhenStopped: 0..1;
59+ revive: 0..1;
60+ _temporarilyBlockHeartBeating: 0..1;
61+ _isHidden: 0..1;
62+ _isHeartBeatInstalled: 0..1;
63+ _customRenderer: 0..1;
64+ _lastFrame: 0..((1 shl 8)-1);
65+ _isDetaching: 0..1;
66+ RESERVED: 0..((1 shl 7)-1);
67+ );
68+ end;
69+ _NSProgressIndicatorReserved1: id;
70+ public
71+ procedure setIndeterminate(newValue: ObjCBOOL); message 'setIndeterminate:';
72+ function isIndeterminate: ObjCBOOL; message 'isIndeterminate';
73+ procedure setBezeled(newValue: ObjCBOOL); message 'setBezeled:';
74+ function isBezeled: ObjCBOOL; message 'isBezeled';
75+ procedure setControlTint(newValue: NSControlTint); message 'setControlTint:';
76+ function controlTint: NSControlTint; message 'controlTint';
77+ procedure setControlSize(newValue: NSControlSize); message 'setControlSize:';
78+ function controlSize: NSControlSize; message 'controlSize';
79+ procedure setDoubleValue(newValue: double); message 'setDoubleValue:';
80+ function doubleValue: double; message 'doubleValue';
81+ procedure incrementBy (delta: double); message 'incrementBy:';
82+ procedure setMinValue(newValue: double); message 'setMinValue:';
83+ function minValue: double; message 'minValue';
84+ procedure setMaxValue(newValue: double); message 'setMaxValue:';
85+ function maxValue: double; message 'maxValue';
86+ procedure setUsesThreadedAnimation(newValue: ObjCBOOL); message 'setUsesThreadedAnimation:';
87+ function usesThreadedAnimation: ObjCBOOL; message 'usesThreadedAnimation';
88+ procedure startAnimation (sender: id); message 'startAnimation:';
89+ procedure stopAnimation (sender: id); message 'stopAnimation:';
90+ procedure setStyle(newValue: NSProgressIndicatorStyle); message 'setStyle:';
91+ function style: NSProgressIndicatorStyle; message 'style';
92+ procedure sizeToFit; message 'sizeToFit';
93+ procedure setDisplayedWhenStopped(newValue: ObjCBOOL); message 'setDisplayedWhenStopped:';
94+ function isDisplayedWhenStopped: ObjCBOOL; message 'isDisplayedWhenStopped';
95+ end;
96+
97+ { TForm1 }
98+
99+ TForm1 = class(TForm)
100+ Button1: TButton;
101+ SpinnerButton: TButton;
102+ CircleButton: TButton;
103+ Bar2Button: TButton;
104+ StopButton: TButton;
105+ BarTimer: TTimer;
106+ CircleTimer: TTimer;
107+ procedure Button1Click(Sender: TObject);
108+ procedure Bar2ButtonClick(Sender: TObject);
109+ procedure CircleTimerUpdate(Sender: TObject);
110+ procedure SpinnerButtonClick(Sender: TObject);
111+ procedure CircleButtonClick(Sender: TObject);
112+ procedure StopButtonClick(Sender: TObject);
113+ procedure FormActivate(Sender: TObject);
114+ procedure BarTimerUpdate(Sender: TObject);
115+ private
116+
117+ public
118+
119+ end;
120+
121+var
122+ Form1: TForm1;
123+ myIndicatorBar: NSProgressIndicator;
124+ myCircleBar: NSProgressIndicator;
125+ myIndicatorBar2: NSProgressIndicator;
126+ mySpinner: NSProgressIndicator;
127+ myView: NSView;
128+
129+implementation
130+
131+{$R *.lfm}
132+
133+{ TForm1 }
134+
135+// Determinate bar
136+procedure TForm1.Button1Click(Sender: TObject);
137+begin
138+ myIndicatorBar := NSProgressIndicator.alloc.initWithFrame(NSMakeRect(30,20,200,20)); // bar
139+ myIndicatorBar.setMinValue(0);
140+ myIndicatorBar.setMaxValue(30);
141+ myIndicatorBar.setStyle(0); // 1 = circle; 0 = bar
142+ myIndicatorBar.setIndeterminate(False);
143+ myView.addSubview(myIndicatorBar);
144+ BarTimer.enabled := True;
145+end;
146+
147+// Determinate circle
148+procedure TForm1.CircleButtonClick(Sender: TObject);
149+begin
150+ myCircleBar := NSProgressIndicator.alloc.initWithFrame(NSMakeRect(10,30,80,80)); // circle
151+ myCircleBar.setStyle(1); // 1 = circle; 0 = bar
152+ myCircleBar.setIndeterminate(False);
153+ myView.addSubview(myCircleBar);
154+ CircleTimer.enabled := True;
155+end;
156+
157+// Indeterminate spinner
158+procedure TForm1.SpinnerButtonClick(Sender: TObject);
159+begin
160+ mySpinner := NSProgressIndicator.alloc.initWithFrame(NSMakeRect(130,80,40,40));
161+ mySpinner.setIndeterminate(True);
162+ mySpinner.setStyle(1); // 1 = spinner; 0 = bouncing bar
163+ mySpinner.setUsesThreadedAnimation(True);
164+ mySpinner.setDisplayedWhenStopped(False);
165+ mySpinner.startAnimation(Nil);
166+ myView.addSubview(mySpinner);
167+end;
168+
169+// Indeterminate bar2
170+procedure TForm1.Bar2ButtonClick(Sender: TObject);
171+begin
172+ myIndicatorBar2 := NSProgressIndicator.alloc.initWithFrame(NSMakeRect(30,130,200,20));
173+ myIndicatorBar2.setIndeterminate(True);
174+ myIndicatorBar2.setStyle(0); // 1 = spinner; 0 = bouncing bar
175+ myIndicatorBar2.setUsesThreadedAnimation(True);
176+ myIndicatorBar2.setDisplayedWhenStopped(False);
177+ myIndicatorBar2.startAnimation(Nil);
178+ myView.addSubview(myIndicatorBar2);
179+end;
180+
181+// Stop all
182+procedure TForm1.StopButtonClick(Sender: TObject);
183+begin
184+ BarTimer.Enabled := False;
185+ CircleTimer.Enabled := False;
186+ mySpinner.stopAnimation(Nil);
187+ myCircleBar.setDoubleValue(0);
188+ myIndicatorBar.setDoubleValue(0);
189+ myIndicatorBar2.stopAnimation(Nil);
190+end;
191+
192+// Get the form's view once for use later
193+procedure TForm1.FormActivate(Sender: TObject);
194+begin
195+ myView := NSView(Form1.Handle);
196+end;
197+
198+// Update bar progress
199+procedure TForm1.BarTimerUpdate(Sender: TObject);
200+begin
201+ myIndicatorBar.incrementBy(0.1);
202+end;
203+
204+// Update circle progress
205+procedure TForm1.CircleTimerUpdate(Sender: TObject);
206+begin
207+ myCircleBar.incrementBy(0.5);
208+end;
209+
210+finalization
211+
212+// Cleanup
213+myIndicatorBar.release;
214+myCircleBar.release;
215+mySpinner.release;
216+myIndicatorBar2.release;
217+
218+end.
219+```
220+
221+Full project source code is available from [SourceForge](https://sourceforge.net/p/lazarus-wiki-projects/code/ci/master/tree/laz_progress_indicators/).
222+
223+## See also
224+
225+- [[Sample Graphics|BGRAControls BGRAFlashProgressBar control]]
226+- [[KControls|KControls TKPercentProgressBar control]]
227+- [[JVCL Components|JVCL Components JvSpecialProgress component]]
228+
229+## External links
230+
231+- [Apple: NSProgressIndicator](https://developer.apple.com/documentation/appkit/nsprogressindicator)
232+
233+---
234+*From the Free Pascal wiki, page "macOS Progress Indicators", as it stood on 2021-11-20 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
235+Category: Code
236+Category: macOS

Back to history