# Dynamically Update both a HorizontalGauge range and the value

I'm developing a demonstration that allows students to explore the location of a point on a number line simultaneously at various scales. I'll show a very simplified version here to get to the nub of my problem.

The Integers scale, has a range of {-30,30}. It's length is 60 units. n is restricted to that range.

The Tenths scale, having a length of 10 units, should also contain or display n.

The image shows the screen display when n = 13.2...

The upper marker can be moved by clicking and dragging. Whenever the marker moves to a different interval, of {-30,-20},{-20,-10},{-10,0},{0,10},{10,20},{20,30} the range of the lower scale is updated. This is fine. But the marker on the bottom scale cannot be dragged.

Here's the code:

Manipulate[
DynamicModule[{n = 10.123},
Column[{
HorizontalGauge[Dynamic@n, {-30, 30},
ImageSize -> {600, Automatic}],
If[show > 1,
Dynamic@HorizontalGauge[Dynamic@n, bounds[n, 10],
GaugeFaceStyle -> RGBColor[1., 0.83, 0.67],
ImageSize -> {600, Automatic}], ""]}]],
{{show, 2, "show to"}, {1 -> "Integers", 2 -> "Tenths"}},
Initialization :> (
bounds[m_, r_] :=
Module[{z = Round[m, r]},
Which[
(z >= 0 \[And] m <= z) \[Or] (z < 0 \[And] m <= z), {z - r, z},
(z >= 0 \[And] m > z) \[Or] (z < 0 \[And] m > z), {z, z + r},
True, "error"]])]


I've tried placing and removing Dynamic on the critical line,

 Dynamic@HorizontalGauge[Dynamic@n, bounds[n, 10]


to no avail. I have not been able to both (1) allow the bottom marker to be draggable and (2) automatically reset the range of the lower scale (when a value from the upper scale goes outside of the current range on the bottom scale.

I've looked at various postings on Dyanmic (542 postings have used the tag "Dynamic"!) but haven't been able to solve the problem. Frankly, I continue to find the behavior of Dynamic mystifying. For instance why does the following not work?

         HorizontalGauge[Dynamic@k, bounds[Dynamic@k, 10]


I've also tried defining n as an invisible control (ControlType->None) with only limited success.

Any help would be appreciated.

## Update

Kuba has provided a very workable solution to the above formulation. However, I would like to be able to extend it beyond two scales. Here is the current version of the code, based on Kuba's contribution:

DynamicModule[
{n = 10.123, m = 10.123, p = 10.123},
Manipulate[
Refresh[Print@RandomReal[];
Column[{
(*Integer Scale*)
HorizontalGauge[Dynamic[n, (n = m = #) &], {-30, 30},
BaseStyle -> 16,
GaugeFaceStyle -> White,
(*ScaleRanges\[Rule]bounds[n,10],*)
ScaleRangeStyle ->
If[show > 1, RGBColor[1., 0.83, 0.67], White]
ScaleDivisions -> {10, 2},
ImageSize -> w
],
(*Tenths Scale*)
Dynamic@If[show > 1,
Dynamic[
HorizontalGauge[Dynamic[n, (n = p = #) &], bounds[m, 10],
GaugeMarkers -> Blue,
BaseStyle -> 14,
GaugeFaceStyle -> RGBColor[1., 0.83, 0.67],

(*ScaleRanges\[Rule]bounds[Dynamic@z,1],*)
ScaleRangeStyle ->
If[show > 2, RGBColor[0.8, 0.75, 1.],
RGBColor[1., 0.83, 0.67]],
ImageSize -> {600, Automatic}],

TrackedSymbols :> {m}], ""],

(*Hundredths Scale*)
Dynamic@If[show > 2,
Dynamic[HorizontalGauge[Dynamic[n], bounds[p, 1],
BaseStyle -> 14,
GaugeFaceStyle -> RGBColor[0.8, 0.75, 1.],
(*ScaleRanges\[Rule]bounds[x,.1],*)

ScaleRangeStyle ->
If[show > 3, RGBColor[0.96, 1., 0.31],
RGBColor[0.8, 0.75, 1.]],
ScaleDivisions -> {5, 4},

ImageSize -> {600, Automatic}],
TrackedSymbols :> {p}], ""]
}], None],

{{show, 3, "show to"}, {1 -> "Integers", 2 -> "Tenths",
3 -> "Hundredths"(*,4\[Rule]"Thousandths",
5\[Rule]"Ten-Thousandths"*)}},

Initialization :> (
w = {600, Automatic};
bounds[m_, r_] :=
Module[{z = Round[m, r]},
Which[(z >= 0 \[And] m <= z) \[Or] (z < 0 \[And] m <= z), {z -
r, z}, (z >= 0 \[And] m > z) \[Or] (z < 0 \[And] m > z), {z,
z + r}, True, "error"]])]]


When run, it looks like this:

If we slide the upper marker, it will update the range of the middle scale, as required, but it does not update the range of the bottom scale. The general goal is to have any marker control the ranges of all the scales beneath it.

BTW, I plan to add two extra scales, for thousandths, and ten-thousandths. That's why the solution needs to be general.

• I decided to use time to improve performance. Unfortunately this postpones explanation :/. Good luck :) – Kuba Feb 25 '15 at 21:17

Few notes: try to avoid Manipulate for complex things. When you have multiple controllers (of the same variable) inside body of Manipulate it triggers evaluation unless you use nested Dynamic/Refresh.

Moreover, referring your last example, take a look at: Function[{m, r}, Round[m, r]][Dynamic[5.5], 1].

DynamicModule[{n = 10.123, interval = {10, 20}},

Manipulate[
(*1*) Refresh[

Column[{
(*2*)   HorizontalGauge[ Dynamic[n, (n = #; interval = bounds[#, 10]) &], {-30, 30},
ImageSize -> {600, Automatic}],
(*3*)   Dynamic @ If[show > 1,
(*4*)                Dynamic[miniG[interval] , TrackedSymbols :> {interval}],
""]
}]
,
None],

{{show, 2, "show to"}, {1 -> "Integers", 2 -> "Tenths"}},
Initialization :> (
bounds[m_, r_] :=  Module[{z = Round[m, r]},
Which[(z >= 0 ∧ m <= z) ∨ (z < 0 ∧ m <= z), {z -  r, z},
(z >= 0 ∧ m > z) ∨ (z < 0 ∧ m > z), {z, z + r},
True, "error"]];
(*5*) miniG[int_] :=  miniG[int] =  HorizontalGauge[Dynamic[n], int,
ImageSize -> {600, Automatic}];

)]

]
`