Button bar active segment by calculation

Hi there,

the Active segment of a button bar can be set using a calculation, which is great.

My question is when is this calculation evaluated, what triggers it ? I am breaking my :tooth: on this.

Thanks

I don't think we can know exactly but we can guess:

  1. Layout Load
  2. Record Load
  3. Is the button in a location that will be visible (or is it on an object that is not being displayed)?
  4. Does the button have a hide calc? Will it be visible?

You know that the result of the calculation must be the name of the button segment to be marked as active, yes?

3- It is displayed, but the Layout has graphics objects that I don't understand purposes. I need to redo the Layout
4- No hide calc

The calculation is set to a global variable, and when I change the value of that variable, I refresh the Button bar. Could the use of a global variable be problematic, it is set to a segment name ?

In a simple test file this code works.

Set Variable [ $$activeSegment ; "NavBtnBar_Invoice" ]
Refresh Object [ "NavBtnBar" ]
  1. Buttonbar is named "NavBtnBar". It has three segments, labelled "Invoice", "Customer","Product"
  2. The button segments are named (object name not button label) "NavBtnBar_Invoice", "NavBtnBar_Customer", "NavBtnBar_Product"
  3. Active segment calculation is "$$activeSegment"
  4. create a script using the script steps above.

To see the active button segment being changed, select any segment except "invoice" then run the script. If you have set everything up correctly the "invoice" segment is displayed in the active state.

Edit:

  1. if the calculation uses a field in the current record, and that field is modified, that would trigger an immediate update.
  2. the calculation can use a field in a related record, and that will trigger an update
  3. rearrange the steps above for easier understanding
1 Like

@Malcolm

I have tested this with a different Button Bar, lets call it BB2 and it's working. But it's not working with the one I want to use this.

First here is the context. I have a Button Bar with 9 segments, lets call it BB1, 9 being the maximum. At this time only 6 of them are used. I don't want to hide the 3 unused segments because I don't want the use segments to resize. How do I do this ? I use Conditional Formatting to have the unused segments "kind of invisible". You can't see them, but if you click on of the hidden segments the active segment is automatically changed. When that happens, I want to change back the active segment to the one that was active before the hidden segment was touched/clicked. But for for this Button Bar it does not work.

For BB2, the one that works, I changed the name of the segments, and I can see these names in the popup menu used to set the default active segment. The names are "Fr" and "En".

But with BB1, the names of the segments are not shown in the popup menu. These are the names as seen in the left pane:

BBar Named Segment 1

As you can see the names are "SE01" to "SE09".

Now, look what I get in the popup menu:

BBar Named Segment 2

The default object names. By the way Specify is set to $$MySegment. When an invisible button is clicked, I set $$MySegment to "<Segment m" & "x" & ">" where x is the segment number. And the previously active segment is not back active.

You said

why ?

In my case, I guess that the contents of $$MySegment is not changed when clicking an invisible button.

Do you understand what's going on ? Regarding the button names not reflected in the popup menu, I cleared the name I specified, and set them back, but is still get .

Thanks

Why select any segment except "invoice"? So that you can see clearly, when the script runs, that the active segment changes from the active segment to "invoice".

Are you confusing the button segment name with the button segment label? The screen shots are showing the button segment labels. The button segment name is set in the first inspector panel.

ObjectName

No I am not confusing. If you change the name in Objects in the left Pane, this will be reflected in the Name field you show. You may also do it the other way.

There is another difference between the Button Bars: the one that works is horizontal, the one that don't work is vertical. I change the horizontal on to vertical and it still works.

If these are the object names of the button segments then they are the names that you want to set $$MySegment to.

Be careful to ensure that they are the object name. The object pane will display the Object Name if one is present. But use other values if the object name is empty. If the object name is empty, in the case of buttons, it will display the segment label. If the button label is a calculation, it displays "calculation." If the button label is empty, it displays "Button".

In the picture, the first segment is labelled "a", and has the name "SEG01". None of the other segments have names. The second segment has a simple string label "b". The third segment has no label at all. The fourth segment is a very simple string calculation. The label is not evaluated, it is shown as "Calculation". (If you use numbers as your button labels they will be interpreted as calculations.)

I use a different technique to hide button bar segments without them resizing. Let's say I want a button bar with six segments. I then make a button bar with twelve segments. Six of these are active segments. The other are inactive segments – they do nothing. I then use hide conditions to display the active and inactive segments I want. You could style the inactive segments in such a way as to make them transparent.

Hope this helps.

1 Like

I guess we agree that my segments all have a name (object name). I did try this (segment "SE02" being current):

Set Variable [ $$Segment ; Value: "SE01"]
Refresh Object [ Object Name: "MyButtonBar"; Repetition: 1]

That didn't work. I also tried refreshing the button itself:

Refresh Object [ Object Name: "SE01"; Repetition: 1]

That also didn't work.

I keep thinking that the fact the popup menu for Active segments does not display the object names but indicates that the Button Bar is broken. If only I was able to get the Active segment from the Button Bar, I could confirm or not my hypothesis.

You have a working example, rebuilding a new button based on that cannot be as long as this thread.

It's completely normal for the active segment popup to display <Segment x>. It does it whenever the label is NOT a simple string.

The image below shows the active segment pop-up for the screen shot shown above. When the label is a string, it displays the label. When the label is empty, or is a calculation, it displays <Segment x>

SCR-20230210-c2c

Spot on ! All the labels are calculated. I am looking for threads in the Community about what I am trying to do. I found this for example:

You can set the active segment on the button bar to false, give the button bar an object name in the inspector, then use refresh object on the button bar after the button is used.

Emphasis is mine. What that means is that setting the active segment programmatically is not that easily done (is rocket science).

I have a few things to test plus more reading to do.

1 Like

It is very easy. Using a global variable as the calculation for the active segment, and two lines of script, you have complete control over the active state of the button. [See my post above]

Many people seem to have the wrong expectation of Refresh Object[].

Refresh Object[] does not update the layout to display the object in its original/default state.

Refresh Object[] updates the layout to display an object in its current state.

Buttons are usually being displayed in their current state, when the current state matches the display state the Refresh Object[] script step doesn't affect the layout display. The only way that you'll ever see a mismatch between the current state and the display state is when a button bar's active segment has been defined by specifying a calculation. When the result of the calculation has been changed, usually by a script, possibly by data entry, a mismatch can occur. To ensure that the display state of a button properly reflects the current state of the calculation use the Refresh Object script step to update the display.

HowToSelectActiveSegments.fmp12 (228 KB)

3 Likes

Note: Any button bar segment calculation that 1) uses a GET () that is record level relevant and 2) is in a portal, will not work - at least all those I have tried so far. For whatever reason, the segment calc looks at the layout base context and NOT the portal context. Pull the same calc outside the portal located button, and it works fine.

Also, button bar active states in a list view, highlights the button in every row. To resolve, set the button bar dialog's specify calculation to 1 (or true), and only the button the row being clicked, displays as active.

Any given button bar segment can be conditionally formatted individually, if the formula is set to TRUE. Makes it easy to hide icons, for instance, on selective buttons.

2 Likes

Sorry for the delay in answering. Here is the solution, and it works very well.

Each Button on the Button Bar must be given a name, if not it will not work. See this screen capture

  1. The top button on the bar is selected
  2. In the the left most Tab of the Inspector, the Object name of this button, not what the button displays, is set.
  3. In the Objects Tab of the left pane in Layout mode, the name is displayed. If something else is displayed, the the button Name is not set, and it will not be possible to programatically set the active button.

One more setting is needed on the Button Bar properties

The Active Segment is specified in this field. Note the value is Specify.... Lets see what the PopupMenu choices are

image

Click on Specify... and

image

we have the Specify Calculation window ! I use a global variable that is set to the name of the specific button, for example "SE01". And that's it !

1 Like

Glad i found this. I did already spend all Sat, Sum of this trying to figure it out myself. Very disappointingly this is a lot of work of hardwiring stuff. Thanks to you and to Claris no thank you!

Why no Claris thank you ? I used what Claris provided to full extent, and it worked pretty good. I used the same layout for many screens that had different menus - there were two button bars - and it each time and it was fast on a fifth generation iPad. I bought a new iPad 10th gen because the old one was slower and slower in other applications.

True that would be nice to have composite layouts, where a layout could embed sub-layout(s). I don't know it that's possible with FileMaker Pro, but it's already possible with Claris Studio which is very impressive !

I didn't ask for composite layouts just ButtonBars in a sense where I don't need to hardwire every segment with object names and explicitly address them and setup individually. The good old repeating fields can do though. How they behave is counter intuitive especially if you place the same button bar on a different layout you open in a new window. The default active segment won't stick. But your "trick"/work-around with explicitly setting them to a global variable and refreshing the individual object did it. ROCKET SCIENCE!

1 Like