File: ShuttleSystem.dox2

package info (click to toggle)
audacity 3.7.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 125,252 kB
  • sloc: cpp: 358,238; ansic: 75,458; lisp: 7,761; sh: 3,410; python: 1,503; xml: 1,385; perl: 854; makefile: 122
file content (179 lines) | stat: -rw-r--r-- 6,764 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/**********************************************************************

  Audacity: A Digital Audio Editor

  ShuttleSystem.dox2

  James Crook

********************************************************************//**

\page ShuttleSystem The Shuttle System

\section ShuttleIntro Introduction

The classes ShuttleGui, ShuttleCli, ShuttleGuiBase and Shuttle were 
designed to simplify repetitive code that moves data around.  Common
repetitive tasks in Audacity are creating dialogs, moving data in and 
out of dialogs and converting from binary to text formats.

\section ShuttleSplit ShuttleGui Vs ShuttleGuiBase

ShuttleGuiBase is slated for \ref WidgetMigration . It contains functions
that work with widgets that are in wxWidgets.  The derived class, 
ShuttleGui, contains extensions that are specific to Audacity widgets.  
It isn't slated for widget migration.

\section ShuttleGuiInit Initialising ShuttleGui

A common idiom in using the ShuttleGui is as follows  - this example 
comes from AudioIOPrefs::Populate() :

\code
   // Code is from a dialog class, so 'this' is a pointer to the dialog
   ShuttleGui S(this, eIsCreatingFromPrefs); // Create the shuttle.
   PopulateOrExchange(S); // Use it.
\endcode

\p S is a temporary object, only kept for as long as needed to actually do
the one exchange.

The first line creates and initialises the ShuttleGui object, setting it 
up for creating a dialog's contents using information about initial values 
from the global preferences.

The \p PopulateOrExchange() function is here being used to populate the dialog.
The same function can be called from elsewhere, later, with a different \p S to 
exchange data.  

The instance of ShuttleGui, \p S, shown in the example above isn't needed 
after returning from \p PopulateOrExchange().

\section ShuttleGuiMethods ShuttleGui Methods

ShuttleGui has several kinds of methods.

 - Layout methods like ShuttleGui::StartHorizontalLay(), used to start 
 a piece of GUI that is to be laid out horizontally.  Use 
 ShuttleGui::EndHorizontalLay() to end such a section.  This is a simple 
 wrapper for the wxWidgets wxBoxSizer.  It has the advantage that the 
 Shuttle keeps track of the sizer.  You do not need to.  You do not need
 to provide a name for the sizer.  This shortens the code.  

\code
   // Example of using a Start/End pair
   S.StartHorizontalLay()
   {
   ... Add controls that you want in the horizontal layout
   }
   S.EndHorizontalLay()
\endcode

The \p { \p } braces are optional, just add them where they improve
readability.


 - \p Add methods, like ShuttleGui::AddCheckBox().  This adds the check box 
 and returns a pointer to it.  You use \p Add methods when you don't want
 ShuttleGui to handle the data exchange.  It just creates the control and
 adds it into the current sizer.

\code
  // Example of calling an Add method
      S.AddChoice( _("Script:"),_("(a) Basic Operation"), &mScripts );
\endcode

 - \p Tie methods, like ShuttleGui::TieCheckBox().  This creates the check 
 box as above, returning a pointer to it.  It also facilitates 
 exchange of data with the control.

\code
  // Example of calling a Tie method
      S.TieChoice( _("Device:"), mDevice,
         wxT(""), mmPlayNames, mmPlayLabels );
\endcode

So \p Tie methods and \p Add methods are very similar.  The \p Tie 
methods have more parameters to them.  You have to specify what you 
are exchanging with.  There are many name overloaded variants on \p Tie 
methods to suit different circumstances.  Exchanging an integer with 
a text box uses a different overload to exchanging a string with the text box.

In the example above, \p mDevice is a \p wxString variable passed by reference
to the function.  This allows ShuttleGui both to read and write to it.  Which
happens depends on how \p S has been configured.

With both \p Add and \p Tie you can optionally specify a windows Id.  Use code
like the following:

\code
   // Example of using a windows Id that we chose.  
   S.Id( idSplashScreen ).TieCheckBox( _("Show Splash Screen"),
      wxT("\Inits\Splash"), true );
\endcode

Where you don't specify an Id, ShuttleGui will assign the Id's sequentially.  

\section ShuttleGuiLayoutTips ShuttleGui Layout Tips

ShuttleGui wraps wxWidget sizers, and the wxWidgets sizer system can sometimes 
itself be confusing.  The most common problem is finding that controls don't
resize at all for some reason.

Resizing requires that 'stretchiness' propagate all the way down from the 
ultimate parent window.  Any sizers that is not using \p wxEXPAND will cause
everything within in it to retain the size it had when the GUI was created,
i.e. it will not resize when the window does.  A very common idiom is to
use \p wxEXPAND but with an expand proportion of '0'.  That still allows 
expansion but <b>not</b> in the main direction.  By contrast using 
\p wxALIGN_LEFT prevents expansion in either direction.

Many of the \p Add and \p Tie functions are designed with a two column layout in 
mind.  So use an idiom like this:

\code
   // The '1' in the next line indicates a resizable wxStaticBox.
   S.StartStatic( _("Recording"), 1 );
   {
      S.StartTwoColumn();
      S.TieChoice( _("Device:"), wxT("RecordingDevice"), 
         wxT(""), mmPlayNames, mmPlayLabels );
      S.TieChoice( _("Channels:"), wxT("RecordChannels"), 
         wxT("2"), mmChannelNames, mmChannelLabels );
      S.EndTwoColumn();
   }
\endcode

The prompts \p 'Device:' and \p 'Channels:' will land in the first column and the
actual choice controls will land in the second column.  All of this is 
inside a \p wxStaticBox with the name \p 'Recording' on it.

To make the choice controls stretch when the \p wxStaticBox grows or shrinks, 
adjust the code to read:

\code

   // This idiom may be simplified when new functions are added to ShuttleGui
   S.StartStatic( _("Recording"), 1 );
   {
      S.StartMultiColumn(2, wxEXPAND);
      S.SetStretchyCol(1);
      S.TieChoice( _("Device:"), wxT("RecordingDevice"), 
         wxT(""), mmPlayNames, mmPlayLabels );
      S.TieChoice( _("Channels:"), wxT("RecordChannels"), 
         wxT("2"), mmChannelNames, mmChannelLabels );
      S.EndMultiColumn();
   }
\endcode


\section ShuttleGuiInternals ShuttleGui Internals

ShuttleGui cleans up the classes which use it.  Parts of its own internal
code are quite repetitive, doing the same thing for different widgets with
slightly different options - e.g. a wxTextCtrl with an integer value or with
a string.  To make the internals of ShuttleGui cleaner, it uses class 
WrappedType.  Also compound functions are formed by chaining
together shorter functions.  This makes it much easier to add new options.

*//********************************************************************/