Hi Erik,
Thanks for the kind words, I'm glad you find the idiom useful. I should give a fair warning that it may be a bit heavy-duty for some tasks. When you can get away with it, it's better to have simpler interdependencies such as the one sketched above by Hans, adapted here:
Manipulate[
Module[{data = {}, rawData, dataR, dataL, totalData},
drawSample :=
AppendTo[data, RandomSample[Range[populationSize], sampleSize]];
Do[drawSample, {trials}];
rawData = Flatten[data];
dataR = Sort[rawData, Greater];
dataL = Sort[rawData];
totalData = Join[dataL, dataR];
BarChart[Drop[totalData, {1, Length[totalData], 2}]]],
{{populationSize, 20}, sampleSize, 50, 1},
{{sampleSize, 6}, 1, populationSize, 1},
{{trials, 5}, 1, 10},
TrackedSymbols -> True]
Here, we've still prevented the bad interaction between populationSize and sampleSize by simply making them dynamic complementary bounds of each other. (As mentioned, Hans actually did this first in a slightly different way in his answer. Furthermore, these dependency semantics, though different, are probably more useful and certainly more elegant than what I chose to implement .)
Manipulate controls are most often Manipulator objects, but can be other types as described in the Details subsection of ref/Manipulate.
The # (or Slot symbol) inside the custom control specification I gave refers to the first (and only) argument given to the pure function I define. Note that I'm using the {u, func} control specification format described in the Details subsection of ref/Manipulate. The first argument given to func when this specification format is used is Dynamic
. Since we want to slightly alter the dynamic update behavior of u, we Append a custom update function to it. The way a custom update function for a Dynamic object must be written is specified in the Details subsection of ref/Dynamic.
About the gauges... yes indeed, I noticed an odd thing, too. By some quick and shallow testing, it seems that the second argument given to the Dynamic update function by a gauge is an ordered pair, seemingly the coordinates of the gauge indicator in the gauge graphic, rather than the symbol to be updated as it is with all other controls I'm more familiar with. You can work around this easily enough by ignoring the second argument 'expr' and updating the relevant control variable directly:
Manipulate[
Module[{data = {}, rawData, dataR, dataL, totalData},
drawSample :=
AppendTo[data, RandomSample[Range[populationSize], sampleSize]];
Do[drawSample, {trials}];
rawData = Flatten[data];
dataR = Sort[rawData, Greater];
dataL = Sort[rawData];
totalData = Join[dataL, dataR];
BarChart[Drop[totalData, {1, Length[totalData], 2}]]],
{{populationSize, 20},
AngularGauge[
Append[#,
Function[val,
populationSize = Round@val;
sampleSize = Min[populationSize, sampleSize],
{HoldAll}]], {1, 50}] &},
{{sampleSize, 6}, 1, populationSize, 1},
{{trials, 5}, 1, 10}]
For more details and for the only good foundation you can have before setting off in more complicated directions, nothing beats browsing the dynamics tutorials mentioned in my previous post as well as the Details subsections of the reference pages of the many symbols involved in all this. Browse the examples at these pages and modify/re-evaluate/interact with them. Comfort comes with experience, and experience only comes with time invested.
Finally, here's another good, general "springboard" resource for things like this:
http://reference.wolfram.com/mathematica/guide/CustomInterfaceConstruction.html
--William